diff options
author | Greg Hudson <ghudson@mit.edu> | 1997-09-14 17:50:06 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 1997-09-14 17:50:06 +0000 |
commit | ac16f380e349fa39ec7e26bccb5456cb300006a5 (patch) | |
tree | c07ca88af97b4f6b77d28a2dc723d2e4621ed302 /server | |
parent | d33e482744fad80d95cdd89ed380c5b8401e49bf (diff) |
Pull in sources from zephyr locker. See /mit/zephyr/repository for
detailed change information.
Diffstat (limited to 'server')
42 files changed, 8933 insertions, 15534 deletions
diff --git a/server/BUGS b/server/BUGS deleted file mode 100644 index ba58741..0000000 --- a/server/BUGS +++ /dev/null @@ -1,2 +0,0 @@ -* race conditions may still exist... -* two renegade servers won't find each other. diff --git a/server/Imakefile b/server/Imakefile deleted file mode 100644 index fcf0232..0000000 --- a/server/Imakefile +++ /dev/null @@ -1,76 +0,0 @@ -/**/# Copyright 1988 Massachusetts Institute of Technology. -/**/# -/**/# For copying and distribution information, see the file -/**/# "mit-copyright.h". -/**/# -/**/# $Source$ -/**/# $Author$ -/**/# $Header$ -/**/# - -#if defined(SYSLOG_COMPAT42) -SYSLOG_OBJ= ../clients/syslogd/syslog.o -SYSLOG_DEF= -I../clients/syslogd -#else -SYSLOG_OBJ= -SYSLOG_DEF= -#endif - -#ifdef __NetBSD__ -OSLIBS=-lcompat /* for insque() */ -#endif - -XDEFS = $(SYSLOG_DEF) -DCONCURRENT - -SRCS= access.c \ - bdump.c \ - class.c \ - client.c \ - common.c \ - dispatch.c \ - hostm.c \ - kopt.c \ - kstuff.c \ - main.c \ - server.c \ - subscr.c \ - timer.c \ - uloc.c \ - version.c \ - zsrv_err.c \ - zstring.c - -OBJS= access.o \ - bdump.o \ - class.o \ - client.o \ - common.o \ - dispatch.o \ - hostm.o \ - kopt.o \ - kstuff.o \ - main.o \ - server.o \ - subscr.o \ - timer.o \ - uloc.o \ - zsrv_err.o \ - zstring.o - -error_table(zsrv_err) -SimpleProgram(zephyrd,$(OBJS) $(SYSLOG_OBJ) version.o $(ZLIB) $(ZLIBDES), $(ZLIBS) $(OSLIBS), $(ATHETCDIR)) -install_man(zephyrd.8,zephyrd.8) -install_file(default.subscriptions,$(ZETCDIR)) - -create_dir($(ZACLDIR)) -install:: - $(RM) $(DESTDIR)$(ZACLDIR)/?*.acl - $(CP) acl/?* $(DESTDIR)$(ZACLDIR) - -depend:: zsrv_err.h version.h -$(OBJS): zsrv_err.h - -version.o: version.h -version.h: $(SRCS) - $(RM) version.h - sh new_vers.sh diff --git a/server/Makefile.in b/server/Makefile.in new file mode 100644 index 0000000..9a4cf56 --- /dev/null +++ b/server/Makefile.in @@ -0,0 +1,67 @@ +SHELL = /bin/sh + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +datadir=@datadir@ +confdir=@confdir@ +sbindir=@sbindir@ +lsbindir=@lsbindir@ + +includedir=${prefix}/include +mandir=${prefix}/man +libdir=${exec_prefix}/lib + +srcdir=@srcdir@ +top_srcdir=@top_srcdir@ +BUILDTOP=.. +VPATH=@srcdir@ +CC=@CC@ +INSTALL=@INSTALL@ +COMPILE_ET=@COMPILE_ET@ + +DEBUG=-O +CFLAGS=${DEBUG} -DCONFDIR=\"${confdir}\" -I${top_srcdir}/h -I${BUILDTOP}/h \ + -I. @CPPFLAGS@ +LDFLAGS=${DEBUG} -L${BUILDTOP}/lib/zephyr @ET_LDFLAGS@ @LDFLAGS@ +LIBS=-lzephyr @LIBS@ -lcom_err + +OBJS= zsrv_err.o access.o acl_files.o bdump.o class.o client.o common.o \ + dispatch.o kopt.o kstuff.o main.o server.o subscr.o timer.o uloc.o \ + zstring.o realm.o version.o + +all: zephyrd + +zephyrd: ${OBJS} ${BUILDTOP}/lib/zephyr/libzephyr.a @ETDEP@ + ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LIBS} + +zsrv_err.c zsrv_err.h: zsrv_err.et + ${COMPILE_ET} ${srcdir}/zsrv_err.et + +version.o: version.h + +version.h: always + sh ${srcdir}/new_vers.sh + +check: + +# No dependency on zephyrd, to avoid rebuilding version.o. +install: + ${INSTALL} -m 755 -s zephyrd ${DESTDIR}${sbindir} + ${INSTALL} -m 644 ${srcdir}/zephyrd.8 ${DESTDIR}${mandir}/man8 + ${INSTALL} -m 644 ${srcdir}/default.subscriptions ${DESTDIR}${confdir} + rm -f ${DESTDIR}${confdir}/acl/?*.acl + cp ${srcdir}/acl/?*.acl ${DESTDIR}${confdir}/acl + chmod 644 ${DESTDIR}${confdir}/acl/* + +clean: + rm -f ${OBJS} zephyrd zsrv_err.[ch] + +always: + +${OBJS}: zserver.h zsrv_err.h timer.h zsrv_conf.h zstring.h access.h acl.h +${OBJS}: ${top_srcdir}/h/internal.h ${top_srcdir}/h/sysdep.h +${OBJS}: ${BUILDTOP}/h/config.h ${BUILDTOP}/h/zephyr/zephyr.h +${OBJS}: ${BUILDTOP}/h/zephyr/zephyr_err.h + +.PHONY: all check install clean always + diff --git a/server/access.c b/server/access.c index 9550904..325b911 100644 --- a/server/access.c +++ b/server/access.c @@ -12,9 +12,11 @@ */ #include <zephyr/mit-copyright.h> +#include "zserver.h" +#include <com_err.h> #if !defined (lint) && !defined (SABER) -static char rcsid_access_c[] = +static const char rcsid_access_c[] = "$Id$"; #endif @@ -24,8 +26,8 @@ static char rcsid_access_c[] = * * int access_check(notice, acl, accesstype) * ZNotice_t *notice; - * ZAcl_t *acl; - * ZAccess_t accesstype; + * Acl *acl; + * Access accesstype; * * void access_init(); * @@ -39,14 +41,8 @@ static char rcsid_access_c[] = * routines and the support needed by the Zephyr server. */ -#include <sys/param.h> -#ifdef SOLARIS -#include <sys/filio.h> -#endif -#include "zserver.h" - /* - * Our private types for the acl_types field in the ZAcl_t structure. + * Our private types for the acl_types field in the Acl structure. * -TYT 8/14/90 */ #define ACL_XMT 1 @@ -54,18 +50,9 @@ static char rcsid_access_c[] = #define ACL_IWS 4 #define ACL_IUI 8 -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -static void check_acl P((ZAcl_t *acl)); -static void check_acl_type P((ZAcl_t *acl, ZAccess_t accesstype, - int typeflag)); -static void access_setup P((int first)); - -#undef P +static void check_acl __P((Acl *acl)); +static void check_acl_type __P((Acl *acl, Access accesstype, int typeflag)); +static void access_setup __P((int first)); /* * check access. return 1 if ok, 0 if not ok. @@ -73,195 +60,176 @@ static void access_setup P((int first)); int access_check(sender, acl, accesstype) - char *sender; - ZAcl_t *acl; - ZAccess_t accesstype; + char *sender; + Acl *acl; + Access accesstype; { - char buf[MAXPATHLEN]; /* holds the real acl name */ - char *prefix; - int flag; - int retval; - - switch (accesstype) { - case TRANSMIT: - prefix = "xmt"; - flag = ACL_XMT; - break; - case SUBSCRIBE: - prefix = "sub"; - flag = ACL_SUB; - break; - case INSTWILD: - prefix = "iws"; - flag = ACL_IWS; - break; - case INSTUID: - prefix = "iui"; - flag = ACL_IUI; - break; - default: - syslog(LOG_ERR, "unknown access type %d", (int) accesstype); - return(0); - } - if (!(acl->acl_types) & flag) /* no acl ==> no restriction - ==> thumbs up */ - return (1); - (void) sprintf(buf, "%s%s-%s.acl", - ZEPHYR_ACL_DIR, - prefix, - acl->acl_filename); - /* - * If we can't load it (because it probably doesn't exist), - * we deny access. - */ + char buf[MAXPATHLEN]; /* holds the real acl name */ + char *prefix; + int flag; + int retval; + + switch (accesstype) { + case TRANSMIT: + prefix = "xmt"; + flag = ACL_XMT; + break; + case SUBSCRIBE: + prefix = "sub"; + flag = ACL_SUB; + break; + case INSTWILD: + prefix = "iws"; + flag = ACL_IWS; + break; + case INSTUID: + prefix = "iui"; + flag = ACL_IUI; + break; + default: + syslog(LOG_ERR, "unknown access type %d", (int) accesstype); + return 0; + } + if (!(acl->acl_types & flag)) /* no acl ==> no restriction */ + return 1; + sprintf(buf, "%s/%s-%s.acl", acl_dir, prefix, acl->acl_filename); + /* + * If we can't load it (because it probably doesn't exist), + * we deny access. + */ #if 0 - zdbug ((LOG_DEBUG, "checking %s for %s", buf, sender)); + zdbug ((LOG_DEBUG, "checking %s for %s", buf, sender)); #endif - retval = acl_load(buf); - if (retval < 0) { - syslog(LOG_DEBUG, "Error in acl_load of %s for %s", buf, sender); - return(0); - } - return (acl_check(buf, sender)); + retval = acl_load(buf); + if (retval < 0) { + syslog(LOG_DEBUG, "Error in acl_load of %s for %s", buf, sender); + return 0; + } + return acl_check(buf, sender); } static void check_acl(acl) - ZAcl_t *acl; + Acl *acl; { - acl->acl_types = 0; - check_acl_type (acl, TRANSMIT, ACL_XMT); - check_acl_type (acl, SUBSCRIBE, ACL_SUB); - check_acl_type (acl, INSTWILD, ACL_IWS); - check_acl_type (acl, INSTUID, ACL_IUI); + acl->acl_types = 0; + check_acl_type(acl, TRANSMIT, ACL_XMT); + check_acl_type(acl, SUBSCRIBE, ACL_SUB); + check_acl_type(acl, INSTWILD, ACL_IWS); + check_acl_type(acl, INSTUID, ACL_IUI); } static void check_acl_type(acl, accesstype, typeflag) - ZAcl_t *acl; - ZAccess_t accesstype; - int typeflag; + Acl *acl; + Access accesstype; + int typeflag; { - char buf[MAXPATHLEN]; /* holds the real acl name */ - char *prefix; - - switch (accesstype) { - case TRANSMIT: - prefix = "xmt"; - break; - case SUBSCRIBE: - prefix = "sub"; - break; - case INSTWILD: - prefix = "iws"; - break; - case INSTUID: - prefix = "iui"; - break; - default: - syslog(LOG_ERR, "unknown access type %d", (int) accesstype); - return; - } - (void) sprintf(buf, "%s%s-%s.acl", - ZEPHYR_ACL_DIR, - prefix, - acl->acl_filename); - if (!access(buf, F_OK)) - acl->acl_types |= typeflag; + char buf[MAXPATHLEN]; /* holds the real acl name */ + char *prefix; + + switch (accesstype) { + case TRANSMIT: + prefix = "xmt"; + break; + case SUBSCRIBE: + prefix = "sub"; + break; + case INSTWILD: + prefix = "iws"; + break; + case INSTUID: + prefix = "iui"; + break; + default: + syslog(LOG_ERR, "unknown access type %d", (int) accesstype); + return; + } + sprintf(buf, "%s/%s-%s.acl", acl_dir, prefix, acl->acl_filename); + if (!access(buf, F_OK)) + acl->acl_types |= typeflag; } - + /* * Re-init code written by TYT, 8/14/90. * * General plan of action; we reread the registry list, and add any * new restricted classes. If any restricted classes disappear (this - * should be rarely) the ZAcl_t structure is not deallocated; rather, + * should be rarely) the Acl structure is not deallocated; rather, * the acl_types field will be left at zero, since there will be no * acl files for the (non-)restricted class. */ static void -#ifdef __STDC__ -access_setup (int first) -#else access_setup(first) - int first; -#endif + int first; { - char buf[MAXPATHLEN]; - char class_name[512]; /* assume class names <= 511 bytes */ - FILE *registry; - ZAcl_t *acl; - register int len; - register char *colon_idx; - Code_t retval = 0; - - (void) sprintf(buf, "%s%s", ZEPHYR_ACL_DIR, ZEPHYR_CLASS_REGISTRY); - - if ((registry = fopen(buf, "r")) == (FILE *) NULL) { - syslog(LOG_ERR, "no registry available, all classes are free"); - return; + char buf[MAXPATHLEN]; + char class_name[512]; /* assume class names <= 511 bytes */ + FILE *registry; + Acl *acl; + int len; + char *colon_idx; + Code_t retval = 0; + + sprintf(buf, "%s/%s", acl_dir, ZEPHYR_CLASS_REGISTRY); + registry = fopen(buf, "r"); + if (!registry) { + syslog(LOG_ERR, "no registry available, all classes are free"); + return; + } + while (fgets(class_name, 512, registry)) { + colon_idx = strchr(class_name, ':'); + if (colon_idx != NULL) + *colon_idx = '\0'; + else if ((len = strlen(class_name)) != 0) + class_name[len - 1] = '\0'; + acl = 0; + if (!first) { + String *z; + + z = make_string(class_name,1); + acl = class_get_acl(z); + free_string(z); } - while (fgets(class_name, 512, registry) != NULL) { - if ((colon_idx = (char *) strchr(class_name, ':')) != NULL) - *colon_idx = '\0'; - else if ((len = strlen(class_name)) != 0) - class_name[len - 1] = '\0'; - acl = 0; - if (!first) { - ZSTRING *z; - z = make_zstring(class_name,1); - acl = class_get_acl(z); - free_zstring(z); - } - if (!acl) { - acl = (ZAcl_t *) xmalloc(sizeof(ZAcl_t)); - if (!acl) { - syslog(LOG_ERR, "no mem acl alloc"); - abort(); - } - acl->acl_filename = strsave(class_name); - check_acl(acl); + if (!acl) { + acl = (Acl *) malloc(sizeof(Acl)); + if (!acl) { + syslog(LOG_ERR, "no mem acl alloc"); + abort(); + } + acl->acl_filename = strsave(class_name); + check_acl(acl); - if (!first) { - /* Try to restrict already existing class */ - retval = class_restrict (class_name, acl); - if (retval == ZSRV_NOCLASS) - retval = class_setup_restricted (class_name, acl); - } - else - retval = class_setup_restricted (class_name, acl); - } - if (retval) { - syslog(LOG_ERR, "can't restrict %s: %s", - class_name, error_message(retval)); - continue; - } - zdbug((LOG_DEBUG, "restricted %s", class_name)); + if (!first) { + /* Try to restrict already existing class */ + retval = class_restrict(class_name, acl); + if (retval == ZSRV_NOCLASS) + retval = class_setup_restricted(class_name, acl); + } else { + retval = class_setup_restricted(class_name, acl); + } } - (void) fclose(registry); - - return; + if (retval) { + syslog(LOG_ERR, "can't restrict %s: %s", + class_name, error_message(retval)); + continue; + } + zdbug((LOG_DEBUG, "restricted %s", class_name)); + } + fclose(registry); } void -#ifdef __STDC__ -access_init (void) -#else access_init() -#endif { - access_setup (1); + access_setup(1); } void -#ifdef __STDC__ -access_reinit (void) -#else access_reinit() -#endif { - acl_cache_reset (); - access_setup (0); + acl_cache_reset(); + access_setup(0); } diff --git a/server/access.h b/server/access.h index df1201d..32507e3 100644 --- a/server/access.h +++ b/server/access.h @@ -17,36 +17,28 @@ #include <zephyr/mit-copyright.h> -#include <zephyr/acl.h> +#include "acl.h" #include "zstring.h" -#include "unix.h" - -typedef enum _ZAccess_t { - TRANSMIT, /* use transmission acl */ - SUBSCRIBE, /* use subscription acl */ - INSTWILD, /* use instance wildcard acl */ - INSTUID /* use instance UID identity acl */ -} ZAccess_t; - -typedef struct _ZAcl_t { - char *acl_filename; - int acl_types; /* Flag field indcating which acls - are present. Used ONLY in access.c */ -} ZAcl_t; - -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif + +typedef enum _Access { + TRANSMIT, /* use transmission acl */ + SUBSCRIBE, /* use subscription acl */ + INSTWILD, /* use instance wildcard acl */ + INSTUID /* use instance UID identity acl */ +} Access; + +typedef struct _Acl { + char *acl_filename; + int acl_types; /* Internal; access fields present. */ +} Acl; /* found in access.c */ -extern void access_init P((void)), access_reinit P((void)); +void access_init __P((void)); +void access_reinit __P((void)); /* found in acl_files.c */ -extern int acl_load P((char *)); - -#undef P +int acl_load __P((char *)); /* external data relevant */ extern int zdebug; + diff --git a/server/acl.h b/server/acl.h new file mode 100644 index 0000000..679cd95 --- /dev/null +++ b/server/acl.h @@ -0,0 +1,27 @@ +/* This file is part of the Project Athena Zephyr Notification System. + * It contains definitions for the ACL library + * + * Created by: John T. Kohl + * + * $Source$ + * $Author$ + * $Header$ + * + * Copyright (c) 1987 by the Massachusetts Institute of Technology. + * For copying and distribution information, see the file + * "mit-copyright.h". + */ + +#include <zephyr/mit-copyright.h> + +#ifndef __ACL__ +#define __ACL__ + +int acl_add __P((char *, char *)); +int acl_check __P((char *, char *)); +int acl_delete __P((char *, char *)); +int acl_initialize __P((char *, int)); +void acl_cache_reset __P((void)); + +#endif /* __ACL__ */ + diff --git a/server/acl_files.c b/server/acl_files.c new file mode 100644 index 0000000..27c7f63 --- /dev/null +++ b/server/acl_files.c @@ -0,0 +1,589 @@ +/* This file is part of the Project Athena Zephyr Notification System. + * It contains functions for maintaining Access Control Lists. + * + * Created by: John T. Kohl + * + * $Source$ + * $Author$ + * + * Copyright (c) 1987,1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, see the file + * "mit-copyright.h". + */ + +/* Define this if you really want the ACL-writing code included. */ +/* #define WRITE_ACL */ + +/* + * Stolen from lib/acl_files.c because acl_load needs to be externally + * declared and not statically declared. + */ + +#include <zephyr/mit-copyright.h> +#include "zserver.h" + + +#ifndef SABER +#ifndef lint +static const char rcsid_acl_files_c[] = "$Id$"; +#endif /* lint */ +#endif /* SABER */ + +/*** Routines for manipulating access control list files ***/ + +/* "aname.inst@realm" */ +#define MAX_PRINCIPAL_SIZE (ANAME_SZ + INST_SZ + REALM_SZ + 3) +#define INST_SEP '.' +#define REALM_SEP '@' + +#define LINESIZE 2048 /* Maximum line length in an acl file */ + +#define NEW_FILE "%s.~NEWACL~" /* Format for name of altered acl file */ +#define WAIT_TIME 300 /* Maximum time allowed write acl file */ + +#define CACHED_ACLS 64 /* How many acls to cache */ +#define ACL_LEN 256 /* Twice a reasonable acl length */ + +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define MIN(a,b) (((a)<(b))?(a):(b)) + +#define COR(a,b) ((a!=NULL)?(a):(b)) + +extern int errno; + +extern time_t time(); + +/* Canonicalize a principal name */ +/* If instance is missing, it becomes "" */ +/* If realm is missing, it becomes the local realm */ +/* Canonicalized form is put in canon, which must be big enough to hold + MAX_PRINCIPAL_SIZE characters */ +void acl_canonicalize_principal(principal, canon) + char *principal; + char *canon; +{ + char *end; + char *dot, *atsign; + int len; + + dot = strchr(principal, INST_SEP); + atsign = strchr(principal, REALM_SEP); + + /* Maybe we're done already */ + if (dot != NULL && atsign != NULL) { + if (dot < atsign) { + /* It's for real */ + /* Copy into canon */ + strncpy(canon, principal, MAX_PRINCIPAL_SIZE); + canon[MAX_PRINCIPAL_SIZE-1] = '\0'; + return; + } else { + /* Nope, it's part of the realm */ + dot = NULL; + } + } + + /* No such luck */ + end = principal + strlen(principal); + + /* Get the principal name */ + len = MIN(ANAME_SZ, COR(dot, COR(atsign, end)) - principal); + strncpy(canon, principal, len); + canon += len; + + /* Add INST_SEP */ + *canon++ = INST_SEP; + + /* Get the instance, if it exists */ + if (dot != NULL) { + ++dot; + len = MIN(INST_SZ, COR(atsign, end) - dot); + strncpy(canon, dot, len); + canon += len; + } + + /* Add REALM_SEP */ + *canon++ = REALM_SEP; + + /* Get the realm, if it exists */ + /* Otherwise, default to local realm */ + if (atsign != NULL) { + ++atsign; + len = MIN(REALM_SZ, end - atsign); + strncpy(canon, atsign, len); + canon += len; + *canon++ = '\0'; + } +#ifdef ZEPHYR_USES_KERBEROS + else if (krb_get_lrealm(canon, 1) != KSUCCESS) { + strcpy(canon, KRB_REALM); + } +#endif +} + +#ifdef notdef +/* Get a lock to modify acl_file */ +/* Return new FILE pointer */ +/* or NULL if file cannot be modified */ +/* REQUIRES WRITE PERMISSION TO CONTAINING DIRECTORY */ +static FILE *acl_lock_file(acl_file) + char *acl_file; +{ + struct stat s; + char new[LINESIZE]; + int nfd; + FILE *nf; + int mode; + + if (stat(acl_file, &s) < 0) return(NULL); + mode = s.st_mode; + sprintf(new, NEW_FILE, acl_file); + for (;;) { + /* Open the new file */ + if ((nfd = open(new, O_WRONLY|O_CREAT|O_EXCL, mode)) < 0) { + if (errno == EEXIST) { + /* Maybe somebody got here already, maybe it's just old */ + if (stat(new, &s) < 0) return(NULL); + if (time(0) - s.st_ctime > WAIT_TIME) { + /* File is stale, kill it */ + unlink(new); + continue; + } else { + /* Wait and try again */ + sleep(1); + continue; + } + } else { + /* Some other error, we lose */ + return(NULL); + } + } + + /* If we got to here, the lock file is ours and ok */ + /* Reopen it under stdio */ + if ((nf = fdopen(nfd, "w")) == NULL) { + /* Oops, clean up */ + unlink(new); + } + return(nf); + } +} + +/* Commit changes to acl_file written onto FILE *f */ +/* Returns zero if successful */ +/* Returns > 0 if lock was broken */ +/* Returns < 0 if some other error occurs */ +/* Closes f */ +static int acl_commit(acl_file, f) + char *acl_file; + FILE *f; +{ +#ifdef WRITE_ACL + char new[LINESIZE]; + int ret; + struct stat s; + + sprintf(new, NEW_FILE, acl_file); + if (fflush(f) < 0 + || fstat(fileno(f), &s) < 0 + || s.st_nlink == 0) { + acl_abort(acl_file, f); + return(-1); + } + + ret = rename(new, acl_file); + fclose(f); + return(ret); +#else + abort (); +#endif +} + +/* Abort changes to acl_file written onto FILE *f */ +/* Returns 0 if successful, < 0 otherwise */ +/* Closes f */ +static int acl_abort(acl_file, f) + char *acl_file; + FILE *f; +{ +#ifdef WRITE_ACL + char new[LINESIZE]; + int ret; + struct stat s; + + /* make sure we aren't nuking someone else's file */ + if (fstat(fileno(f), &s) < 0 || s.st_nlink == 0) { + fclose(f); + return(-1); + } else { + sprintf(new, NEW_FILE, acl_file); + ret = unlink(new); + fclose(f); + return(ret); + } +#else + abort (); +#endif +} + +/* Initialize an acl_file */ +/* Creates the file with permissions perm if it does not exist */ +/* Erases it if it does */ +/* Returns return value of acl_commit */ +int +acl_initialize(acl_file, perm) + char *acl_file; + int perm; +{ + FILE *new; + int fd; + + /* Check if the file exists already */ + if ((new = acl_lock_file(acl_file)) != NULL) { + return(acl_commit(acl_file, new)); + } else { + /* File must be readable and writable by owner */ + if ((fd = open(acl_file, O_CREAT|O_EXCL, perm|0600)) < 0) { + return(-1); + } else { + close(fd); + return(0); + } + } +} + +#endif /* notdef */ + +/* Eliminate all whitespace character in buf */ +/* Modifies its argument */ +static void nuke_whitespace(buf) + char *buf; +{ + char *pin, *pout; + + for (pin = pout = buf; *pin != '\0'; pin++) + if (!isspace(*pin)) *pout++ = *pin; + *pout = '\0'; /* Terminate the string */ +} + +/* Hash table stuff */ + +struct hashtbl { + int size; /* Max number of entries */ + int entries; /* Actual number of entries */ + char **tbl; /* Pointer to start of table */ +}; + +/* Make an empty hash table of size s */ +static struct hashtbl *make_hash(size) + int size; +{ + struct hashtbl *h; + + if (size < 1) size = 1; + h = (struct hashtbl *) malloc(sizeof(struct hashtbl)); + h->size = size; + h->entries = 0; + h->tbl = (char **) calloc(size, sizeof(char *)); + return(h); +} + +/* Destroy a hash table */ +static void +destroy_hash(h) + struct hashtbl *h; +{ + int i; + + for (i = 0; i < h->size; i++) { + if (h->tbl[i] != NULL) free(h->tbl[i]); + } + free(h->tbl); + free(h); +} + +/* Compute hash value for a string */ +static unsigned int +hashval(s) + char *s; +{ + unsigned hv; + + for (hv = 0; *s != '\0'; s++) { + hv ^= ((hv << 3) ^ *s); + } + return(hv); +} + +/* Add an element to a hash table */ +static void add_hash(h, el) + struct hashtbl *h; + char *el; +{ + unsigned hv; + char *s; + char **old; + int i; + +#if 0 + fprintf (stderr, "adding %s to acl hash %08X\n", el, h); +#endif + /* Make space if it isn't there already */ + if (h->entries + 1 > (h->size >> 1)) { + old = h->tbl; + h->tbl = (char **) calloc(h->size << 1, sizeof(char *)); + for (i = 0; i < h->size; i++) { + if (old[i] != NULL) { + hv = hashval(old[i]) % (h->size << 1); + while(h->tbl[hv] != NULL) hv = (hv+1) % (h->size << 1); + h->tbl[hv] = old[i]; + } + } + h->size = h->size << 1; + free(old); + } + + hv = hashval(el) % h->size; + while(h->tbl[hv] != NULL && strcmp(h->tbl[hv], el)) hv = (hv+1) % h->size; + s = (char *) malloc(strlen(el)+1); + strcpy(s, el); + h->tbl[hv] = s; + h->entries++; +} + +/* Returns nonzero if el is in h */ +static int +check_hash(h, el) + struct hashtbl *h; + char *el; +{ + unsigned hv; + +#if 0 + fprintf (stderr, "looking for %s in acl %08X\n", el, h); +#endif + for (hv = hashval(el) % h->size; h->tbl[hv]; hv = (hv + 1) % h->size) { +#if 0 + fprintf (stderr, "\tstrcmp (%s,...)\n", h->tbl[hv]); +#endif + if (!strcmp(h->tbl[hv], el)) { +#if 0 + fprintf (stderr, "success!\n"); +#endif + return 1; + } + } +#if 0 + fprintf (stderr, "failure\n"); +#endif + return 0; +} + +struct acl { + char filename[LINESIZE]; /* Name of acl file */ + struct hashtbl *acl; /* Acl entries */ +}; + +static struct acl acl_cache[CACHED_ACLS]; + +static int acl_cache_count = 0; +static int acl_cache_next = 0; + +/* Returns < 0 if unsuccessful in loading acl */ +/* Returns index into acl_cache otherwise */ +/* Note that if acl is already loaded, this is just a lookup */ +int acl_load(name) + char *name; +{ + int i; + FILE *f; + char buf[MAX_PRINCIPAL_SIZE]; + char canon[MAX_PRINCIPAL_SIZE]; + + /* See if it's there already */ + for (i = 0; i < acl_cache_count; i++) { + if (!strcmp(acl_cache[i].filename, name)) + goto got_it; + } + + /* It isn't, load it in */ + /* maybe there's still room */ + if (acl_cache_count < CACHED_ACLS) { + i = acl_cache_count++; + } else { + /* No room, clean one out */ + i = acl_cache_next; + acl_cache_next = (acl_cache_next + 1) % CACHED_ACLS; + if (acl_cache[i].acl) { + destroy_hash(acl_cache[i].acl); + acl_cache[i].acl = (struct hashtbl *) 0; + } + } + + /* Set up the acl */ + strcpy(acl_cache[i].filename, name); + /* Force reload */ + acl_cache[i].acl = (struct hashtbl *) 0; + + got_it: + /* + * See if we need to reload the ACL + */ + if (acl_cache[i].acl == (struct hashtbl *) 0) { + /* Gotta reload */ +#if 0 + fprintf (stderr, "attempting to load %s\n", name); +#endif + if ((f = fopen(name, "r")) == NULL) { +#if 0 + perror (name); +#endif + return -1; + } + if (acl_cache[i].acl) destroy_hash(acl_cache[i].acl); + acl_cache[i].acl = make_hash(ACL_LEN); + while(fgets(buf, sizeof(buf), f) != NULL) { + nuke_whitespace(buf); + acl_canonicalize_principal(buf, canon); + add_hash(acl_cache[i].acl, canon); + } + fclose(f); + } + return(i); +} + +/* + * This destroys all cached ACL's so that new ones will be loaded in + * the next time they are requested. + */ +void +acl_cache_reset() +{ + int i; + + /* See if it's there already */ + for (i = 0; i < acl_cache_count; i++) + if (acl_cache[i].acl) { + destroy_hash(acl_cache[i].acl); + acl_cache[i].acl = (struct hashtbl *) 0; + } + acl_cache_count = 0; + acl_cache_next = 0; + } + + +/* Returns nonzero if it can be determined that acl contains principal */ +/* Principal is not canonicalized, and no wildcarding is done */ +acl_exact_match(acl, principal) + char *acl; + char *principal; +{ + int idx; + +#if 0 + fprintf (stderr, "checking for %s in %s\n", principal, acl); +#endif + return((idx = acl_load(acl)) >= 0 + && check_hash(acl_cache[idx].acl, principal)); +} + +/* Returns nonzero if it can be determined that acl contains principal */ +/* Recognizes wildcards in acl. */ +int +acl_check(acl, principal) + char *acl; + char *principal; +{ + char buf[MAX_PRINCIPAL_SIZE]; + char canon[MAX_PRINCIPAL_SIZE]; + char *instance, *realm; + int p, i, r; + + /* Parse into principal, instance, and realm. */ + acl_canonicalize_principal(principal, canon); + instance = (char *) strchr(canon, INST_SEP); + *instance++ = 0; + realm = (char *) strchr(instance, REALM_SEP); + *realm++ = 0; + + for (p = 0; p <= 1; p++) { + for (i = 0; i <= 1; i++) { + for (r = 0; r <= 1; r++) { + sprintf(buf, "%s%c%s%c%s", (p) ? canon : "*", INST_SEP, + (i) ? instance : "*", REALM_SEP, (r) ? realm : "*"); + if (acl_exact_match(acl, buf)) + return 1; + } + } + } + + return(0); +} + +#ifdef notdef +/* Adds principal to acl */ +/* Wildcards are interpreted literally */ +int +acl_add(acl, principal) + char *acl; + char *principal; +{ + int idx; + int i; + FILE *new; + char canon[MAX_PRINCIPAL_SIZE]; + + acl_canonicalize_principal(principal, canon); + + if ((new = acl_lock_file(acl)) == NULL) return(-1); + if ((acl_exact_match(acl, canon)) + || (idx = acl_load(acl)) < 0) { + acl_abort(acl, new); + return(-1); + } + /* It isn't there yet, copy the file and put it in */ + for (i = 0; i < acl_cache[idx].acl->size; i++) { + if (acl_cache[idx].acl->tbl[i] != NULL) { + if (fputs(acl_cache[idx].acl->tbl[i], new) == NULL + || putc('\n', new) != '\n') { + acl_abort(acl, new); + return(-1); + } + } + } + fputs(canon, new); + putc('\n', new); + return(acl_commit(acl, new)); +} + +/* Removes principal from acl */ +/* Wildcards are interpreted literally */ +int +acl_delete(acl, principal) + char *acl; + char *principal; +{ + int idx; + int i; + FILE *new; + char canon[MAX_PRINCIPAL_SIZE]; + + acl_canonicalize_principal(principal, canon); + + if ((new = acl_lock_file(acl)) == NULL) return(-1); + if ((!acl_exact_match(acl, canon)) + || (idx = acl_load(acl)) < 0) { + acl_abort(acl, new); + return(-1); + } + /* It isn't there yet, copy the file and put it in */ + for (i = 0; i < acl_cache[idx].acl->size; i++) { + if (acl_cache[idx].acl->tbl[i] != NULL + && strcmp(acl_cache[idx].acl->tbl[i], canon)) { + fputs(acl_cache[idx].acl->tbl[i], new); + putc('\n', new); + } + } + return(acl_commit(acl, new)); +} +#endif /* notdef */ diff --git a/server/bdump.c b/server/bdump.c index e304933..17f99db 100644 --- a/server/bdump.c +++ b/server/bdump.c @@ -11,27 +11,15 @@ * For copying and distribution information, see the file * "mit-copyright.h". */ - + #include <zephyr/mit-copyright.h> - -#ifndef lint -#ifndef SABER -static char rcsid_bdump_c[] = "$Id$"; -#endif /* SABER */ -#endif /* lint */ - #include "zserver.h" #include <sys/socket.h> -#include <signal.h> -#include <sys/param.h> /* for BSD */ - -/* inconsistent header files... */ -#ifdef SignalIgnore -#undef SIG_IGN -#define SIG_IGN SignalIgnore -#undef SIG_DFL -#define SIG_DFL SignalDefault -#endif +#include <com_err.h> + +#ifndef lint +static const char rcsid_bdump_c[] = "$Id$"; +#endif /* lint */ /* * External functions are: @@ -45,7 +33,7 @@ static char rcsid_bdump_c[] = "$Id$"; * ZNotice_t *notice; * int auth; * struct sockaddr_in *who; - * ZServerDesc_t *server; + * Server *server; * * Code_t bdump_send_list_tcp(kind, port, class, inst, opcode, * sender, recip, lyst, num) @@ -55,42 +43,30 @@ static char rcsid_bdump_c[] = "$Id$"; * char *lyst[]; * int num; */ - -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif -static void close_bdump P((void* arg)); -static Code_t bdump_send_loop P((register ZServerDesc_t *server, char *vers)), - bdump_ask_for P((char *inst)), - bdump_recv_loop P((ZServerDesc_t *server)); -static void bdump_get_v1 P((ZNotice_t *, int, struct sockaddr_in *, - ZServerDesc_t *)); -static void bdump_get_v1a P((ZNotice_t *notice, int auth, - struct sockaddr_in *who, ZServerDesc_t *server)); -static Code_t get_packet P((caddr_t packet, int len, int *retlen)); -static Code_t extract_sin P((ZNotice_t *notice, struct sockaddr_in *target)); -static Code_t send_done P((void)); -static Code_t send_list P((ZNotice_Kind_t kind, int port, char *class_name, - char *inst, char *opcode, char *sender, char *recip, - char **lyst, int num)); -static Code_t send_host_register P((ZHostList_t *host)); -static Code_t sbd_loop P((struct sockaddr_in *from)); -static Code_t gbd_loop P((ZServerDesc_t *server)); -static Code_t send_normal_tcp P((ZNotice_Kind_t kind, int port, - char *class_name, - char *inst, char *opcode, char *sender, - char *recip, char *message, int len)); -static int net_read P((FILE *f, register char *buf, register int len)); -static int net_write P((FILE *f, register char *buf, int len)); -static int setup_file_pointers P((void)); -static void shutdown_file_pointers P((void)); -static void cleanup P((ZServerDesc_t *server)); - -#ifdef KERBEROS -static int get_tgt P((void)); +static void close_bdump __P((void* arg)); +static Code_t bdump_send_loop __P((Server *server)), +bdump_ask_for __P((char *inst)), +bdump_recv_loop __P((Server *server)); +static void bdump_get_v12 __P((ZNotice_t *, int, struct sockaddr_in *, + Server *)); +static Code_t get_packet __P((void *packet, int len, int *retlen)); +static Code_t extract_sin __P((ZNotice_t *notice, struct sockaddr_in *target)); +static Code_t send_done __P((void)); +static Code_t send_list __P((ZNotice_Kind_t kind, int port, char *class_name, + char *inst, char *opcode, char *sender, + char *recip, char **lyst, int num)); +static Code_t send_normal_tcp __P((ZNotice_Kind_t kind, int port, + char *class_name, + char *inst, char *opcode, char *sender, + char *recip, char *message, int len)); +static int net_read __P((FILE *f, char *buf, int len)); +static int net_write __P((FILE *f, char *buf, int len)); +static int setup_file_pointers __P((void)); +static void shutdown_file_pointers __P((void)); +static void cleanup __P((Server *server)); + +#ifdef ZEPHYR_USES_KERBEROS static long ticket_time; static char my_realm[REALM_SZ]; @@ -98,15 +74,12 @@ static char my_realm[REALM_SZ]; #define tkt_lifetime(val) ((long) val * 5L * 60L) #ifndef NOENCRYPTION -C_Block serv_key; -Sched serv_ksched; +extern C_Block serv_key; +extern Sched serv_ksched; #endif -#endif /* KERBEROS */ +#endif /* ZEPHYR_USES_KERBEROS */ -#undef P - -static timer bdump_timer; -static int bdump_inited; +static Timer *bdump_timer; static int live_socket = -1; static FILE *input, *output; static struct sockaddr_in bdump_sin; @@ -115,668 +88,575 @@ static int cancel_outgoing_dump; #endif int bdumping; +int bdump_concurrent; extern char *bdump_version; - + /* * Functions for performing a brain dump between servers. */ - + /* * offer the brain dump to another server */ - + void bdump_offer(who) - struct sockaddr_in *who; + struct sockaddr_in *who; { - Code_t retval; - char buf[512], *addr, *lyst[2]; -#ifndef KERBEROS - int bdump_port = IPPORT_RESERVED - 1; -#endif /* !KERBEROS */ + Code_t retval; + char buf[512], *addr, *lyst[2]; +#ifndef ZEPHYR_USES_KERBEROS + int bdump_port = IPPORT_RESERVED - 1; +#endif /* !ZEPHYR_USES_KERBEROS */ #if 1 - zdbug((LOG_DEBUG, "bdump_offer")); + zdbug((LOG_DEBUG, "bdump_offer")); #endif -#ifdef KERBEROS - /* - * when using Kerberos server-server authentication, we can - * use any random local address - */ - if ((bdump_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - syslog(LOG_ERR,"bdump_offer: socket: %m"); - bdump_socket = -1; - return; - } - (void) memset((caddr_t) &bdump_sin, 0, sizeof(bdump_sin)); - /* a port field of 0 makes the UNIX - * kernel choose an appropriate port/address pair */ - - bdump_sin.sin_port = 0; - bdump_sin.sin_addr = my_addr; - bdump_sin.sin_family = AF_INET; - if ((retval = bind(bdump_socket, (struct sockaddr *) &bdump_sin, sizeof(bdump_sin))) < 0) { - syslog(LOG_ERR, "bdump_offer: bind: %m"); - (void) close(bdump_socket); - bdump_socket = -1; - return; - } - if (!bdump_sin.sin_port) { - int len = sizeof(bdump_sin); - if (getsockname(bdump_socket, - (struct sockaddr *)&bdump_sin, &len)) { - syslog(LOG_ERR, "bdump_offer: getsockname: %m"); - (void) close(bdump_socket); - bdump_socket = -1; - return; - } - } -#else /* !KERBEROS */ - /* - * when not using Kerberos, we can't use any old port, we use - * Internet reserved ports instead (rresvport) - */ - if ((bdump_socket = rresvport(&bdump_port)) < 0) { - syslog(LOG_ERR,"bdump_offer: socket: %m"); - bdump_socket = -1; - return; +#ifdef ZEPHYR_USES_KERBEROS + /* + * when using ZEPHYR_USES_KERBEROS server-server authentication, we can + * use any random local address + */ + bdump_socket = socket(AF_INET, SOCK_STREAM, 0); + if (bdump_socket < 0) { + syslog(LOG_ERR,"bdump_offer: socket: %m"); + bdump_socket = -1; + return; + } + memset(&bdump_sin, 0, sizeof(bdump_sin)); + /* a port field of 0 makes the UNIX + * kernel choose an appropriate port/address pair */ + + bdump_sin.sin_port = 0; + bdump_sin.sin_addr = my_addr; + bdump_sin.sin_family = AF_INET; + retval = bind(bdump_socket, (struct sockaddr *) &bdump_sin, + sizeof(bdump_sin)); + if (retval < 0) { + syslog(LOG_ERR, "bdump_offer: bind: %m"); + close(bdump_socket); + bdump_socket = -1; + return; + } + if (!bdump_sin.sin_port) { + int len = sizeof(bdump_sin); + + if (getsockname(bdump_socket, + (struct sockaddr *) &bdump_sin, &len) < 0) { + syslog(LOG_ERR, "bdump_offer: getsockname: %m"); + close(bdump_socket); + bdump_socket = -1; + return; } - (void) memset((caddr_t) &bdump_sin, 0, sizeof(bdump_sin)); - bdump_sin.sin_port = htons((unsigned short)bdump_port); - bdump_sin.sin_addr = my_addr; - bdump_sin.sin_family = AF_INET; - -#endif /* KERBEROS */ - (void) listen(bdump_socket, 1); - - bdump_timer = timer_set_rel(20L, close_bdump, (void *) 0); - FD_SET(bdump_socket, &interesting); - nfildes = max(bdump_socket, srv_socket) + 1; - - - addr = inet_ntoa(bdump_sin.sin_addr); - (void) sprintf(buf, "%d", ntohs(bdump_sin.sin_port)); - lyst[0] = addr; - lyst[1] = buf; + } +#else /* !ZEPHYR_USES_KERBEROS */ + /* + * when not using ZEPHYR_USES_KERBEROS, we can't use any old port, we use + * Internet reserved ports instead (rresvport) + */ + bdump_socket = rresvport(&bdump_port); + if (bdump_socket < 0) { + syslog(LOG_ERR,"bdump_offer: socket: %m"); + bdump_socket = -1; + return; + } + memset(&bdump_sin, 0, sizeof(bdump_sin)); + bdump_sin.sin_port = htons((unsigned short) bdump_port); + bdump_sin.sin_addr = my_addr; + bdump_sin.sin_family = AF_INET; +#endif /* ZEPHYR_USES_KERBEROS */ + + listen(bdump_socket, 1); - if ((retval = ZSetDestAddr(who)) != ZERR_NONE) { - syslog(LOG_WARNING, "bdump_offer: ZSetDestAddr: %s", - error_message(retval)); - return; - } + bdump_timer = timer_set_rel(20L, close_bdump, NULL); + FD_SET(bdump_socket, &interesting); + nfds = max(bdump_socket, srv_socket) + 1; + + addr = inet_ntoa(bdump_sin.sin_addr); + sprintf(buf, "%d", ntohs(bdump_sin.sin_port)); + lyst[0] = addr; + lyst[1] = buf; + + retval = ZSetDestAddr(who); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "bdump_offer: ZSetDestAddr: %s", + error_message(retval)); + return; + } - /* myname is the hostname */ - /* the class instance is the version number, here it is */ - /* bdump_version, which is set in main */ - (void) send_list(ACKED, sock_sin.sin_port, ZEPHYR_ADMIN_CLASS, - bdump_version, ADMIN_BDUMP, myname, "", lyst, 2); + /* myname is the hostname */ + /* the class instance is the version number, here it is */ + /* bdump_version, which is set in main */ + send_list(ACKED, srv_addr.sin_port, ZEPHYR_ADMIN_CLASS, bdump_version, + ADMIN_BDUMP, myname, "", lyst, 2); #if 1 - zdbug((LOG_DEBUG,"bdump_offer: address is %s/%d\n", - inet_ntoa(bdump_sin.sin_addr), - ntohs(bdump_sin.sin_port))); + zdbug((LOG_DEBUG,"bdump_offer: address is %s/%d\n", + inet_ntoa(bdump_sin.sin_addr), + ntohs(bdump_sin.sin_port))); #endif - return; + return; } - + /* * Accept a connection, and send the brain dump to the other server */ - + void -#ifdef __STDC__ -bdump_send(void) -#else bdump_send() -#endif { - struct sockaddr_in from; - ZServerDesc_t *server; - Code_t retval; - int fromlen = sizeof(from); - int on = 1; -#ifdef POSIX - struct sigaction action; + struct sockaddr_in from; + Server *server; + Code_t retval; + int fromlen = sizeof(from); + int on = 1; +#ifdef _POSIX_VERSION + struct sigaction action; #endif -#ifdef KERBEROS - KTEXT_ST ticket; - AUTH_DAT kdata; +#ifdef ZEPHYR_USES_KERBEROS + KTEXT_ST ticket; + AUTH_DAT kdata; #else - unsigned short fromport; -#endif /* KERBEROS */ + unsigned short fromport; +#endif /* ZEPHYR_USES_KERBEROS */ #if 1 - zdbug((LOG_DEBUG, "bdump_send")); + zdbug((LOG_DEBUG, "bdump_send")); #endif - /* accept the connection, and send the brain dump */ - if ((live_socket = accept(bdump_socket, (struct sockaddr *)&from, - &fromlen)) < 0) { - syslog(LOG_ERR,"bdump_send: accept: %m"); - return; - } - if (setsockopt(live_socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, - sizeof (on)) < 0) - syslog(LOG_WARNING, - "bdump_send: setsockopt (SO_KEEPALIVE): %m"); + /* accept the connection, and send the brain dump */ + live_socket = accept(bdump_socket, (struct sockaddr *) &from, &fromlen); + if (live_socket < 0) { + syslog(LOG_ERR,"bdump_send: accept: %m"); + return; + } + if (setsockopt(live_socket, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, + sizeof(on)) < 0) + syslog(LOG_WARNING, "bdump_send: setsockopt (SO_KEEPALIVE): %m"); -#ifndef KERBEROS - fromport = ntohs(from.sin_port); +#ifndef ZEPHYR_USES_KERBEROS + fromport = ntohs(from.sin_port); #endif -#ifdef POSIX - (void) sigemptyset(&action.sa_mask); - action.sa_flags = 0; - action.sa_handler = SIG_IGN; - (void) sigaction(SIGPIPE, &action, NULL); +#ifdef _POSIX_VERSION + sigemptyset(&action.sa_mask); + action.sa_flags = 0; + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); - START_CRITICAL_CODE; #else - (void) signal(SIGPIPE, SIG_IGN); /* so we can detect failures */ + signal(SIGPIPE, SIG_IGN); /* so we can detect failures */ #endif - from.sin_port = sock_sin.sin_port; /* we don't care what port - it came from, and we need to - fake out server_which_server() */ - server = server_which_server(&from); - if (!server) { - syslog(LOG_ERR, "bdump_send: unknown server?"); - server = limbo_server; - } + from.sin_port = srv_addr.sin_port; /* we don't care what port + * it came from, and we need to + * fake out server_which_server() */ + server = server_which_server(&from); + if (!server) { + syslog(LOG_ERR, "bdump_send: unknown server?"); + server = limbo_server; + } #if 1 - zdbug((LOG_DEBUG, "bdump_send: connection from %s/%d", - inet_ntoa (from.sin_addr), ntohs (from.sin_port))); + zdbug((LOG_DEBUG, "bdump_send: connection from %s/%d", + inet_ntoa(from.sin_addr), ntohs(from.sin_port))); #endif -#ifdef notdef - if (bdumping) { - /* Already bdumping; punt one of the two. If this is a - new host, punt this connection. If it's one we're - already trying to talk to... arbitrary decision: The - connection with the listener at the lower IP address - will be punted. */ - if (!server->zs_dumping) { - zdbug ((LOG_INFO, -"bdump_send: already dumping; breaking new bdump connection from %s", - inet_ntoa (from.sin_addr))); - (void) close (live_socket); - return; - } - /* Should be safe now to get rid of listener socket. */ - (void) close (bdump_socket); - FD_CLR (bdump_socket, &interesting); - bdump_socket = -1; - timer_reset(bdump_timer); - if (ntohl (bdump_sin.sin_addr.s_addr) < ntohl (from.sin_addr.s_addr)) { - /* My address is lower; punt incoming connection. */ - (void) close (live_socket); - return; - } - else - cancel_outgoing_dump = 1; - } -#endif + bdumping = 1; + server->dumping = 1; - bdumping = 1; - server->zs_dumping = 1; - - if (bdump_socket >= 0) { - /* shut down the listening socket and the timer */ - FD_CLR(bdump_socket, &interesting); - (void) close(bdump_socket); - nfildes = srv_socket + 1; - bdump_socket = -1; - timer_reset(bdump_timer); - } + if (bdump_socket >= 0) { + /* shut down the listening socket and the timer. */ + FD_CLR(bdump_socket, &interesting); + close(bdump_socket); + nfds = srv_socket + 1; + bdump_socket = -1; + timer_reset(bdump_timer); + } - /* Now begin the brain dump. */ + /* Now begin the brain dump. */ -#ifdef KERBEROS - /* receive the authenticator */ - if ((retval = GetKerberosData(live_socket, from.sin_addr, &kdata, - SERVER_SERVICE, ZEPHYR_SRVTAB)) - != KSUCCESS) - { - syslog(LOG_ERR, "bdump_send: getkdata: %s", - krb_err_txt[retval]); - cleanup(server); - return; - } - if (get_tgt()) { - cleanup(server); - return; - } - if (strcmp(kdata.pname,SERVER_SERVICE) || - strcmp(kdata.pinst, SERVER_INSTANCE) || - strcmp(kdata.prealm, my_realm)) - { - syslog(LOG_ERR, "bdump_send: peer not zephyr: %s.%s@%s", - kdata.pname, kdata.pinst, kdata.prealm); - cleanup(server); - return; - } - /* authenticate back */ - if ((retval = SendKerberosData(live_socket, &ticket, - SERVER_SERVICE, SERVER_INSTANCE)) != 0) - { - syslog(LOG_ERR,"bdump_send: SendKerberosData: %s", - error_message (retval)); - cleanup(server); - return; - } -#else /* !KERBEROS */ - if ((fromport > IPPORT_RESERVED) || - (fromport < (IPPORT_RESERVED / 2))) { - syslog(LOG_ERR, "bdump_send: bad port from peer: %d", - fromport); - cleanup(server); - return; - } -#endif /* KERBEROS */ +#ifdef ZEPHYR_USES_KERBEROS + /* receive the authenticator */ + retval = GetKerberosData(live_socket, from.sin_addr, &kdata, + SERVER_SERVICE, srvtab_file); + if (retval != KSUCCESS) { + syslog(LOG_ERR, "bdump_send: getkdata: %s", + krb_get_err_text(retval)); + cleanup(server); + return; + } + if (get_tgt()) { + cleanup(server); + return; + } + if (strcmp(kdata.pname, SERVER_SERVICE) || + strcmp(kdata.pinst, SERVER_INSTANCE) || + strcmp(kdata.prealm, ZGetRealm())) { + syslog(LOG_ERR, "bdump_send: peer not zephyr: %s.%s@%s", + kdata.pname, kdata.pinst, kdata.prealm); + cleanup(server); + return; + } + /* authenticate back */ + retval = SendKerberosData(live_socket, &ticket, SERVER_SERVICE, + SERVER_INSTANCE); + if (retval != 0) { + syslog(LOG_ERR,"bdump_send: SendKerberosData: %s", + error_message (retval)); + cleanup(server); + return; + } +#else /* !ZEPHYR_USES_KERBEROS */ + if (fromport > IPPORT_RESERVED || fromport < IPPORT_RESERVED / 2) { + syslog(LOG_ERR, "bdump_send: bad port from peer: %d", fromport); + cleanup(server); + return; + } +#endif /* ZEPHYR_USES_KERBEROS */ - if ((retval = setup_file_pointers()) != 0) { - syslog (LOG_WARNING, "bdump_send: can't set up file pointers: %s", - error_message (retval)); - cleanup(server); - return; - } - if ((retval = sbd_loop(&from)) != ZERR_NONE) { - syslog(LOG_WARNING, "bdump_send: sbd_loop failed: %s", - error_message(retval)); - cleanup(server); - return; - } - if ((retval = gbd_loop(server)) != ZERR_NONE) { - syslog(LOG_WARNING, "bdump_send: gbd_loop failed: %s", - error_message(retval)); - cleanup(server); - return; - } + retval = setup_file_pointers(); + if (retval != 0) { + syslog (LOG_WARNING, "bdump_send: can't set up file pointers: %s", + error_message(retval)); + cleanup(server); + return; + } + retval = bdump_send_loop(server); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "bdump_send: bdump_send_loop failed: %s", + error_message(retval)); + cleanup(server); + return; + } + retval = bdump_recv_loop(server); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "bdump_send: bdump_recv_loop failed: %s", + error_message(retval)); + cleanup(server); + return; + } #if 1 - zdbug((LOG_DEBUG, "bdump_send: finished")); + zdbug((LOG_DEBUG, "bdump_send: finished")); #endif - if (server != limbo_server) { - /* set this guy to be up, and schedule a hello */ - server->zs_state = SERV_UP; - timer_reset(server->zs_timer); - server->zs_timer = timer_set_rel(0L, server_timo, (void *) server); - } + if (server != limbo_server) { + /* set this guy to be up, and schedule a hello */ + server->state = SERV_UP; + timer_reset(server->timer); + server->timer = timer_set_rel(0L, server_timo, server); + } #if 0 - zdbug((LOG_DEBUG,"cleanup sbd")); + zdbug((LOG_DEBUG,"cleanup sbd")); #endif - shutdown_file_pointers (); + shutdown_file_pointers(); -#ifdef POSIX - action.sa_handler = SIG_DFL; - sigaction(SIGPIPE, &action, NULL); +#ifdef _POSIX_VERSION + action.sa_handler = SIG_DFL; + sigaction(SIGPIPE, &action, NULL); #else - (void) signal(SIGPIPE, SIG_DFL); -#endif - bdump_inited = 1; - bdumping = 0; - server->zs_dumping = 0; -#ifdef CONCURRENT - /* Now that we are finished dumping, send all the queued packets */ - server_send_queue(server); + signal(SIGPIPE, SIG_DFL); #endif - END_CRITICAL_CODE; - return; + bdumping = 0; + server->dumping = 0; + /* Now that we are finished dumping, send all the queued packets */ + server_send_queue(server); + return; } /*ARGSUSED*/ static void -bdump_get_v1_guts (notice, auth, who, server) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - ZServerDesc_t *server; +bdump_get_v12 (notice, auth, who, server) + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + Server *server; { - struct sockaddr_in from; - Code_t retval; - int on = 1; -#ifdef POSIX - struct sigaction action; + struct sockaddr_in from; + Code_t retval; + int on = 1; +#ifdef _POSIX_VERSION + struct sigaction action; #endif -#ifdef KERBEROS - KTEXT_ST ticket; - AUTH_DAT kdata; -#else /* !KERBEROS */ - int reserved_port = IPPORT_RESERVED - 1; -#endif /* KERBEROS */ +#ifdef ZEPHYR_USES_KERBEROS + KTEXT_ST ticket; + AUTH_DAT kdata; +#else /* !ZEPHYR_USES_KERBEROS */ + int reserved_port = IPPORT_RESERVED - 1; +#endif /* ZEPHYR_USES_KERBEROS */ - bdumping = 1; - server->zs_dumping = 1; + bdumping = 1; + server->dumping = 1; -#ifdef POSIX - action.sa_flags = 0; - sigemptyset(&action.sa_mask); - action.sa_handler = SIG_IGN; - sigaction(SIGPIPE, &action, NULL); +#ifdef _POSIX_VERSION + action.sa_flags = 0; + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); #else - (void) signal(SIGPIPE, SIG_IGN); /* so we can detect problems */ -#endif /* POSIX */ + signal(SIGPIPE, SIG_IGN); /* so we can detect problems */ +#endif /* _POSIX_VRESION */ - if (bdump_socket >= 0) { - /* We cannot go get a brain dump when someone may - potentially be connecting to us (if that other - server is the server to whom we are connecting, - we will deadlock. so we shut down the listening - socket and the timer */ - FD_CLR(bdump_socket, &interesting); - (void) close(bdump_socket); - nfildes = srv_socket+1; - bdump_socket = -1; - timer_reset(bdump_timer); - } + if (bdump_socket >= 0) { + /* We cannot go get a brain dump when someone may + potentially be connecting to us (if that other + server is the server to whom we are connecting, + we will deadlock. so we shut down the listening + socket and the timer. */ + FD_CLR(bdump_socket, &interesting); + close(bdump_socket); + nfds = srv_socket+1; + bdump_socket = -1; + timer_reset(bdump_timer); + } - if ((retval = extract_sin(notice, &from)) != ZERR_NONE) { - syslog(LOG_ERR, "bdump_get: sin: %s", error_message(retval)); -#ifdef POSIX - action.sa_handler = SIG_DFL; - sigaction(SIGPIPE, &action, NULL); + retval = extract_sin(notice, &from); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "bdump_get: sin: %s", error_message(retval)); +#ifdef _POSIX_VERSION + action.sa_handler = SIG_DFL; + sigaction(SIGPIPE, &action, NULL); #else - (void) signal(SIGPIPE, SIG_DFL); + signal(SIGPIPE, SIG_DFL); #endif - bdumping = 0; - server->zs_dumping = 0; - return; - } - START_CRITICAL_CODE; -#ifndef KERBEROS - if (ntohs(from.sin_port) > IPPORT_RESERVED || - ntohs(from.sin_port) < IPPORT_RESERVED / 2) { - syslog(LOG_ERR, "bdump_get: port not reserved: %d", - ntohs(from.sin_port)); - cleanup(server); - return; - } - live_socket = rresvport(&reserved_port); -#else /* !KERBEROS */ - live_socket = socket(AF_INET, SOCK_STREAM, 0); -#endif /* KERBEROS */ - if (live_socket < 0) { - syslog(LOG_ERR, "bdump_get: socket: %m"); - cleanup(server); - return; - } - if (connect(live_socket, (struct sockaddr *) &from, sizeof(from))) { - syslog(LOG_ERR, "bdump_get: connect: %m"); - cleanup(server); - return; - } - if (setsockopt(live_socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, - sizeof (on)) < 0) - syslog(LOG_WARNING, - "bdump_get: setsockopt (SO_KEEPALIVE): %m"); + bdumping = 0; + server->dumping = 0; + return; + } +#ifndef ZEPHYR_USES_KERBEROS + if (ntohs(from.sin_port) > IPPORT_RESERVED || + ntohs(from.sin_port) < IPPORT_RESERVED / 2) { + syslog(LOG_ERR, "bdump_get: port not reserved: %d", + ntohs(from.sin_port)); + cleanup(server); + return; + } + live_socket = rresvport(&reserved_port); +#else /* !ZEPHYR_USES_KERBEROS */ + live_socket = socket(AF_INET, SOCK_STREAM, 0); +#endif /* ZEPHYR_USES_KERBEROS */ + if (live_socket < 0) { + syslog(LOG_ERR, "bdump_get: socket: %m"); + cleanup(server); + return; + } + if (connect(live_socket, (struct sockaddr *) &from, sizeof(from))) { + syslog(LOG_ERR, "bdump_get: connect: %m"); + cleanup(server); + return; + } + if (setsockopt(live_socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, + sizeof(on)) < 0) + syslog(LOG_WARNING, "bdump_get: setsockopt (SO_KEEPALIVE): %m"); #if 1 - zdbug((LOG_DEBUG, "bdump_get: connected")); + zdbug((LOG_DEBUG, "bdump_get: connected")); #endif - /* Now begin the brain dump. */ + /* Now begin the brain dump. */ -#ifdef KERBEROS - /* send an authenticator */ - if (get_tgt()) { - cleanup(server); - return; - } - if ((retval = SendKerberosData(live_socket, &ticket, - SERVER_SERVICE, SERVER_INSTANCE)) != 0) - { - syslog(LOG_ERR,"bdump_get: %s", - error_message (retval)); - cleanup(server); - return; - } +#ifdef ZEPHYR_USES_KERBEROS + /* send an authenticator */ + if (get_tgt()) { + cleanup(server); + return; + } + retval = SendKerberosData(live_socket, &ticket, SERVER_SERVICE, + SERVER_INSTANCE); + if (retval != 0) { + syslog(LOG_ERR,"bdump_get: %s", error_message(retval)); + cleanup(server); + return; + } #if 1 - zdbug((LOG_DEBUG, "bdump_get: SendKerberosData ok")); + zdbug((LOG_DEBUG, "bdump_get: SendKerberosData ok")); #endif - /* get his authenticator */ - if ((retval = GetKerberosData(live_socket, from.sin_addr, &kdata, - SERVER_SERVICE, ZEPHYR_SRVTAB)) - != KSUCCESS) - { - syslog(LOG_ERR, "bdump_get getkdata: %s",krb_err_txt[retval]); - cleanup(server); - return; - } - /* my_realm is filled in inside get_tgt() */ - if (strcmp(kdata.pname, SERVER_SERVICE) || - strcmp(kdata.pinst, SERVER_INSTANCE) || - strcmp(kdata.prealm, my_realm)) - { - syslog(LOG_ERR, - "bdump_get: peer not zephyr in lrealm: %s.%s@%s", - kdata.pname, kdata.pinst,kdata.prealm); - cleanup(server); - return; - } -#endif /* KERBEROS */ - if ((retval = setup_file_pointers()) != 0) { - syslog (LOG_WARNING, "bdump_get: can't set up file pointers: %s", - error_message (retval)); - cleanup(server); - return; - } - if ((retval = gbd_loop(server)) != ZERR_NONE) { - syslog(LOG_WARNING, "bdump_get: gbd_loop failed: %s", - error_message(retval)); - cleanup(server); - return; - } + /* get his authenticator */ + retval = GetKerberosData(live_socket, from.sin_addr, &kdata, + SERVER_SERVICE, srvtab_file); + if (retval != KSUCCESS) { + syslog(LOG_ERR, "bdump_get getkdata: %s",krb_get_err_text(retval)); + cleanup(server); + return; + } + /* my_realm is filled in inside get_tgt() */ + if (strcmp(kdata.pname, SERVER_SERVICE) || + strcmp(kdata.pinst, SERVER_INSTANCE) || + strcmp(kdata.prealm, my_realm)) { + syslog(LOG_ERR, "bdump_get: peer not zephyr in lrealm: %s.%s@%s", + kdata.pname, kdata.pinst,kdata.prealm); + cleanup(server); + return; + } +#endif /* ZEPHYR_USES_KERBEROS */ + retval = setup_file_pointers(); + if (retval != 0) { + syslog(LOG_WARNING, "bdump_get: can't set up file pointers: %s", + error_message (retval)); + cleanup(server); + return; + } + retval = bdump_recv_loop(server); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "bdump_get: bdump_recv_loop failed: %s", + error_message(retval)); + cleanup(server); + return; + } #if 1 - zdbug((LOG_DEBUG,"bdump_get: gbdl ok")); + zdbug((LOG_DEBUG,"bdump_get: gbdl ok")); #endif - if ((retval = sbd_loop(&from)) != ZERR_NONE) { - syslog(LOG_WARNING, "sbd_loop failed: %s", - error_message(retval)); - cleanup(server); - return; - } + retval = bdump_send_loop(server); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "bdump_send_loop failed: %s", + error_message(retval)); + cleanup(server); + return; + } #if 1 - zdbug((LOG_DEBUG, "bdump_get: gbd finished")); + zdbug((LOG_DEBUG, "bdump_get: gbd finished")); #endif - /* set this guy to be up, and schedule a hello */ - server->zs_state = SERV_UP; - timer_reset(server->zs_timer); - server->zs_timer = timer_set_rel(0L, server_timo, (void *) server); + /* set this guy to be up, and schedule a hello */ + server->state = SERV_UP; + timer_reset(server->timer); + server->timer = timer_set_rel(0L, server_timo, server); #if 1 - zdbug((LOG_DEBUG,"cleanup gbd")); -#endif - shutdown_file_pointers (); -#ifdef POSIX - action.sa_handler = SIG_DFL; - sigaction(SIGPIPE, &action, NULL); -#else - (void) signal(SIGPIPE, SIG_DFL); + zdbug((LOG_DEBUG,"cleanup gbd")); #endif - bdump_inited = 1; - bdumping = 0; - server->zs_dumping = 0; -#ifdef CONCURRENT - /* Now that we are finished dumping, send all the queued packets */ - server_send_queue(server); -#endif - - END_CRITICAL_CODE; - return; -} - -static void -#ifdef __STDC__ -bdump_get_v1(ZNotice_t *notice, int auth, struct sockaddr_in *who, - ZServerDesc_t *server) + shutdown_file_pointers(); +#ifdef _POSIX_VERSION + action.sa_handler = SIG_DFL; + sigaction(SIGPIPE, &action, NULL); #else -bdump_get_v1(notice, auth, who, server) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - ZServerDesc_t *server; + signal(SIGPIPE, SIG_DFL); #endif -{ - if (bdump_socket >= 0) { - /* We cannot go get a brain dump when someone may - potentially be connecting to us (if that other - server is the server to whom we are connecting, - we will deadlock. so we shut down the listening - socket and the timer */ - FD_CLR(bdump_socket, &interesting); - (void) close(bdump_socket); - nfildes = srv_socket + 1; - bdump_socket = -1; - timer_reset(bdump_timer); - } - - bdump_get_v1_guts (notice, auth, who, server); -} + bdumping = 0; + server->dumping = 0; + /* Now that we are finished dumping, send all the queued packets */ + server_send_queue(server); -static void -#ifdef __STDC__ -bdump_get_v1a( ZNotice_t *notice, int auth, struct sockaddr_in *who, - ZServerDesc_t *server) -#else -bdump_get_v1a(notice, auth, who, server) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - ZServerDesc_t *server; -#endif -{ - /* In version 1A, leave the listening file descriptor open; if we - get a connection while we're dumping, one of the two will be - punted. */ - bdump_get_v1_guts (notice, auth, who, server); + return; } void bdump_get(notice, auth, who, server) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - ZServerDesc_t *server; + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + Server *server; { -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif + void (*proc) __P((ZNotice_t *, int, struct sockaddr_in *, Server *)); - void (*proc) P((ZNotice_t *, int, struct sockaddr_in *, ZServerDesc_t *)); - -#undef P - proc = NULL; + proc = NULL; #if 1 - if (zdebug) - syslog(LOG_DEBUG, "bdump_get: bdump v%s avail %s", - notice->z_class_inst, inet_ntoa(who->sin_addr)); + if (zdebug) { + syslog(LOG_DEBUG, "bdump_get: bdump v%s avail %s", + notice->z_class_inst, inet_ntoa(who->sin_addr)); + } #endif - /* - * We do not listen to version "1" or "1A" because they are a - * security threat (they send the CBlock in clear-text). - */ - if (!strcmp (notice->z_class_inst, "1.1") - || !strcmp (notice->z_class_inst, "")) - proc = bdump_get_v1; - if (!strcmp (notice->z_class_inst, "1.1A")) - proc = bdump_get_v1a; - - if (proc) - (*proc) (notice, auth, who, server); - else - syslog(LOG_WARNING, - "bdump_get: Incompatible bdump version '%s' from %s", - notice->z_class_inst, - inet_ntoa(who->sin_addr)); + if (strcmp (notice->z_class_inst, "1.2") == 0) + proc = bdump_get_v12; + + if (proc) { + (*proc)(notice, auth, who, server); + } else { + syslog(LOG_WARNING, + "bdump_get: Incompatible bdump version '%s' from %s", + notice->z_class_inst, + inet_ntoa(who->sin_addr)); + } } /* * Send a list off as the specified notice */ - -int -bdump_send_list_tcp(kind, port, class_name, inst, opcode, sender, recip, - lyst, num) - ZNotice_Kind_t kind; - int port; - char *class_name; - char *inst; - char *opcode; - char *sender; - char *recip; - char **lyst; - int num; + +Code_t +bdump_send_list_tcp(kind, addr, class_name, inst, opcode, sender, recip, lyst, + num) + ZNotice_Kind_t kind; + struct sockaddr_in *addr; + int num; + char *class_name, *inst, *opcode, *sender, *recip, **lyst; { - ZNotice_t notice; - register ZNotice_t *pnotice = ¬ice; /* speed hack */ - char *pack; - int packlen, count; - Code_t retval; - u_short length; - - pnotice->z_kind = kind; - - pnotice->z_port = port; - pnotice->z_class = class_name; - pnotice->z_class_inst = inst; - pnotice->z_opcode = opcode; - pnotice->z_sender = sender; - pnotice->z_recipient = recip; - pnotice->z_default_format = ""; - pnotice->z_num_other_fields = 0; - - if ((retval = ZFormatNoticeList(pnotice, (char **) lyst, num, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) - return(retval); + ZNotice_t notice; + char *pack, addrbuf[100]; + int packlen, count; + Code_t retval; + u_short length; + + retval = ZMakeAscii(addrbuf, sizeof(addrbuf), + (unsigned char *) &addr->sin_addr, + sizeof(struct in_addr)); + if (retval != ZERR_NONE) + return retval; + notice.z_kind = kind; + + notice.z_port = addr->sin_port; + notice.z_class = class_name; + notice.z_class_inst = inst; + notice.z_opcode = opcode; + notice.z_sender = sender; + notice.z_recipient = recip; + notice.z_default_format = ""; + notice.z_num_other_fields = 1; + notice.z_other_fields[0] = addrbuf; + + retval = ZFormatNoticeList(¬ice, lyst, num, &pack, &packlen, ZNOAUTH); + if (retval != ZERR_NONE) + return retval; - length = htons((u_short) packlen); + length = htons((u_short) packlen); - if ((count = net_write(output, (caddr_t) &length, sizeof(length))) != sizeof(length)) - if (count < 0) { - xfree(pack); /* free allocated storage */ - return(errno); - } else { - syslog(LOG_WARNING, "slt (length) xmit: %d vs %d", - sizeof(length),count); - xfree(pack); /* free allocated storage */ - return(ZSRV_PKSHORT); - } + count = net_write(output, (char *) &length, sizeof(length)); + if (count != sizeof(length)) { + if (count < 0) { + free(pack); + return(errno); + } else { + syslog(LOG_WARNING, "slt (length) xmit: %d vs %d", + sizeof(length), count); + free(pack); + return(ZSRV_PKSHORT); + } + } - if ((count = net_write(output, pack, packlen)) != packlen) - if (count < 0) { - xfree(pack); /* free allocated storage */ - return(errno); - } else { - syslog(LOG_WARNING, "slt (packet) xmit: %d vs %d", - packlen, count); - xfree(pack); /* free allocated storage */ - return(ZSRV_PKSHORT); - } - xfree(pack); /* free allocated storage */ - return(ZERR_NONE); + count = net_write(output, pack, packlen); + if (count != packlen) { + if (count < 0) { + free(pack); + return(errno); + } else { + syslog(LOG_WARNING, "slt (packet) xmit: %d vs %d", + packlen, count); + free(pack); + return(ZSRV_PKSHORT); + } + } + free(pack); + return(ZERR_NONE); } - + static void -shutdown_file_pointers () { +shutdown_file_pointers() { if (input) { - (void) fclose (input); + fclose(input); input = 0; } if (output) { - (void) fclose (output); + fclose(output); output = 0; } if (live_socket >= 0) { - (void) close (live_socket); + close(live_socket); live_socket = -1; } } static void cleanup(server) - ZServerDesc_t *server; + Server *server; { -#ifdef POSIX +#ifdef _POSIX_VERSION struct sigaction action; #endif @@ -784,226 +664,86 @@ cleanup(server) zdbug((LOG_DEBUG, "bdump cleanup")); #endif if (server != limbo_server) { - server->zs_state = SERV_DEAD; - timer_reset(server->zs_timer); - server->zs_timer = - timer_set_rel(0L, server_timo, (void *) server); + server->state = SERV_DEAD; + timer_reset(server->timer); + server->timer = timer_set_rel(0L, server_timo, server); } shutdown_file_pointers (); -#ifdef POSIX +#ifdef _POSIX_VERSION action.sa_flags = 0; sigemptyset(&action.sa_mask); action.sa_handler = SIG_DFL; sigaction(SIGPIPE,&action, NULL); #else - (void) signal(SIGPIPE, SIG_DFL); -#endif /* POSIX */ + signal(SIGPIPE, SIG_DFL); +#endif /* _POSIX_VERSION */ bdumping = 0; - server->zs_dumping = 0; -#ifdef CONCURRENT - /* XXX need to flush the server and the updates to it */ -#endif - END_CRITICAL_CODE; - return; + server->dumping = 0; } - -#ifdef KERBEROS -static int + +#ifdef ZEPHYR_USES_KERBEROS +int get_tgt() { - int retval; + /* MIT Kerberos 4 get_svc_in_tkt() requires instance to be writable and + * at least INST_SZ bytes long. */ + static char buf[INST_SZ + 1] = SERVER_INSTANCE; + int retval = 0; + CREDENTIALS cred; #ifndef NOENCRYPTION - Sched *s; + Sched *s; #endif - if (!*my_realm) - if ((retval = krb_get_lrealm(my_realm, 1)) != KSUCCESS) { - syslog(LOG_ERR,"krb_get_lrealm: %s", - krb_err_txt[retval]); - *my_realm = '\0'; - return(1); - } - /* have they expired ? */ - if (ticket_time < NOW - tkt_lifetime(TKTLIFETIME) + 15L) { - /* +15 for leeway */ + if (!*my_realm) { + retval = krb_get_lrealm(my_realm, 1); + if (retval != KSUCCESS) { + syslog(LOG_ERR,"krb_get_lrealm: %s", krb_get_err_text(retval)); + *my_realm = '\0'; + return(1); + } + } + /* have they expired ? */ + if (ticket_time < NOW - tkt_lifetime(TKTLIFETIME) + 15L) { + /* +15 for leeway */ #if 0 - zdbug((LOG_DEBUG,"get new tickets: %d %d %d", - ticket_time, NOW, - NOW - tkt_lifetime(TKTLIFETIME) + 15L)); + zdbug((LOG_DEBUG,"get new tickets: %d %d %d", ticket_time, NOW, + NOW - tkt_lifetime(TKTLIFETIME) + 15L)); #endif - (void) dest_tkt(); - - { - /* - * XXX One version of krb_get_svc_in_tkt wants - * this argument writable and at least INST_SZ - * bytes long. - */ - static char buf[INST_SZ+1] = SERVER_INSTANCE; - - retval = krb_get_svc_in_tkt (SERVER_SERVICE, buf/*XXX*/, - my_realm, - SERVER_SERVICE, SERVER_INSTANCE, - TKTLIFETIME, ZEPHYR_SRVTAB); - } - if (retval != KSUCCESS) { - syslog(LOG_ERR,"get_tgt: krb_get_svc_in_tkt: %s", - krb_err_txt[retval]); - ticket_time = 0L; - return(1); - } else - ticket_time = NOW; + dest_tkt(); -#ifndef NOENCRYPTION - retval = read_service_key(SERVER_SERVICE, SERVER_INSTANCE, - my_realm, 0 /*kvno*/, - ZEPHYR_SRVTAB, serv_key); - if (retval != KSUCCESS) { - syslog(LOG_ERR, "get_tgt: read_service_key: %s", - krb_err_txt[retval]); - return 1; - } - s = (Sched *)check_key_sched_cache(serv_key); - if (s) { - serv_ksched = *s; - } else { - des_key_sched(serv_key, serv_ksched.s); - add_to_key_sched_cache(serv_key, &serv_ksched); - } -#endif /* !NOENCRYPTION */ - } - return(0); -} -#endif /* KERBEROS */ - -static Code_t -sbd_loop(from) - struct sockaddr_in *from; -{ - ZNotice_t bd_notice; - ZPacket_t pack; - ZServerDesc_t *server; - int packlen = sizeof(pack); - Code_t retval; - struct sockaddr_in bogus_from; - char *zeph_version = NULL; - - bogus_from = *from; - bogus_from.sin_port = sock_sin.sin_port; - - while (1) { - packlen = sizeof(pack); - if ((retval = get_packet(pack, packlen, &packlen)) != ZERR_NONE) { - syslog(LOG_ERR, "sbd_loop: notice get: %s", - error_message(retval)); - return(retval); - } - if ((retval = ZParseNotice(pack, packlen, &bd_notice)) != ZERR_NONE) { - syslog(LOG_ERR, "sbd notice parse: %s", - error_message(retval)); - return(retval); - } - if (!zeph_version) { - zeph_version = strsave(bd_notice.z_version); - } -#ifdef DEBUG - if (zdebug) { - char buf[4096]; - - (void) sprintf(buf, - "bdump:%s '%s' '%s' '%s' '%s' '%s'", - ZNoticeKinds[(int) bd_notice.z_kind], - bd_notice.z_class, - bd_notice.z_class_inst, - bd_notice.z_opcode, - bd_notice.z_sender, - bd_notice.z_recipient); - syslog(LOG_DEBUG, buf); - } -#endif /* DEBUG */ - if (!strcmp(bd_notice.z_class_inst, ADMIN_LIMBO)) { - /* he wants limbo */ -#if 1 - zdbug((LOG_DEBUG, "limbo req")); -#endif - if ((retval = bdump_send_loop(limbo_server, - zeph_version)) - != ZERR_NONE) - return(retval); - continue; - } else if (!strcmp(bd_notice.z_class_inst, ADMIN_ME)) { - /* he wants his state */ -#if 1 - zdbug((LOG_DEBUG, "his state req")); -#endif - if ((server = server_which_server(&bogus_from)) != - NULLZSDT) { - if ((retval = bdump_send_loop(server, - zeph_version)) - != ZERR_NONE) - return(retval); - } else { - syslog(LOG_ERR,"sbd_loop: no state"); - if ((retval = send_done()) != ZERR_NONE) - return(retval); - } - continue; - } else if (!strcmp(bd_notice.z_class_inst, ADMIN_YOU)) { - /* he wants my state */ -#if 1 - zdbug((LOG_DEBUG, "my state req")); -#endif - if ((retval = bdump_send_loop(me_server, zeph_version)) - != ZERR_NONE) - return(retval); - break; - } else if (!strcmp(bd_notice.z_class_inst, ADMIN_DONE)) { - break; - } else { - /* what does he want? */ -#if 1 - zdbug((LOG_DEBUG, "unknown req")); -#endif - break; - } - } - if (zeph_version) - xfree(zeph_version); - return(ZERR_NONE); -} - -static Code_t -gbd_loop(server) - ZServerDesc_t *server; -{ - Code_t retval; - - /* - * if we have no hosts in the 'limbo' state (on the limbo server), - * ask for the other server to send us the limbo state. - * Thus we keep track of all the hosts which haven't spoken in a while, - * even in the face of server failure. - */ - if (otherservers[limbo_server_idx()].zs_hosts->q_forw == - otherservers[limbo_server_idx()].zs_hosts) { - if ((retval = bdump_ask_for(ADMIN_LIMBO)) != ZERR_NONE) - return(retval); - if ((retval = bdump_recv_loop(&otherservers[limbo_server_idx()])) != ZERR_NONE) - return(retval); + retval = krb_get_svc_in_tkt(SERVER_SERVICE, buf, ZGetRealm(), + "krbtgt", ZGetRealm(), + TKTLIFETIME, srvtab_file); + if (retval != KSUCCESS) { + syslog(LOG_ERR,"get_tgt: krb_get_svc_in_tkt: %s", + krb_get_err_text(retval)); + ticket_time = 0; + return(1); + } else { + ticket_time = NOW; } - /* Have I been given my own startup info yet? */ - if (!bdump_inited) { - if ((retval = bdump_ask_for(ADMIN_ME)) != ZERR_NONE) - return(retval); - if ((retval = bdump_recv_loop(me_server)) != ZERR_NONE) - return(retval); +#ifndef NOENCRYPTION + retval = read_service_key(SERVER_SERVICE, SERVER_INSTANCE, + ZGetRealm(), 0 /*kvno*/, + srvtab_file, serv_key); + if (retval != KSUCCESS) { + syslog(LOG_ERR, "get_tgt: read_service_key: %s", + krb_get_err_text(retval)); + return 1; + } + s = (Sched *) check_key_sched_cache(serv_key); + if (s) { + serv_ksched = *s; + } else { + des_key_sched(serv_key, serv_ksched.s); + add_to_key_sched_cache(serv_key, &serv_ksched); } - if ((retval = bdump_ask_for(ADMIN_YOU)) != ZERR_NONE) - return(retval); - retval = bdump_recv_loop(server); - return(retval); +#endif /* !NOENCRYPTION */ + } + return(0); } +#endif /* ZEPHYR_USES_KERBEROS */ /* * The braindump offer wasn't taken, so we retract it. @@ -1012,40 +752,22 @@ gbd_loop(server) /*ARGSUSED*/ static void close_bdump(arg) - void * arg; + void * arg; { - if (bdump_socket >= 0) { - FD_CLR(bdump_socket, &interesting); - (void) close(bdump_socket); - nfildes = srv_socket + 1; - bdump_socket = -1; + if (bdump_socket >= 0) { + FD_CLR(bdump_socket, &interesting); + close(bdump_socket); + nfds = srv_socket + 1; + bdump_socket = -1; #if 1 - zdbug((LOG_DEBUG, "bdump not used")); + zdbug((LOG_DEBUG, "bdump not used")); #endif - } else { + } else { #if 1 - zdbug((LOG_DEBUG, "bdump not open")); + zdbug((LOG_DEBUG, "bdump not open")); #endif - } - return; -} - -/* - * Ask the other server to send instruction packets for class instance - * inst - */ - -static Code_t -bdump_ask_for(inst) - char *inst; -{ - Code_t retval; - - /* myname is the hostname */ - retval = send_normal_tcp(ACKED, bdump_sin.sin_port, ZEPHYR_ADMIN_CLASS, - inst, ADMIN_BDUMP, myname, "", - (char *) NULL, 0); - return(retval); + } + return; } /* @@ -1054,535 +776,376 @@ bdump_ask_for(inst) static Code_t bdump_recv_loop(server) - ZServerDesc_t *server; + Server *server; { - ZNotice_t notice; - ZPacket_t packet; - int len; - Code_t retval; - ZClient_t *client = NULLZCNT; - struct sockaddr_in current_who; - int who_valid = 0; - int flushing_subs = 0; -#ifdef KERBEROS - register char *cp; - C_Block cblock; -#endif /* KERBEROS */ -#ifdef CONCURRENT - fd_set readable, initial; - int fd_ready; - struct timeval tv; -#endif /* CONCURRENT */ + ZNotice_t notice; + ZPacket_t packet; + int len; + Code_t retval; + Client *client = NULL; + struct sockaddr_in who; +#ifdef ZEPHYR_USES_KERBEROS + char *cp; + C_Block cblock; +#endif /* ZEPHYR_USES_KERBEROS */ + Realm *realm = NULL; #if 1 - zdbug((LOG_DEBUG, "bdump recv loop")); + zdbug((LOG_DEBUG, "bdump recv loop")); #endif -#ifdef CONCURRENT - FD_ZERO(&initial); - FD_SET(srv_socket, &initial); -#endif /* CONCURRENT */ - - /* do the inverse of bdump_send_loop, registering stuff on the fly */ - while (1) { -#ifdef CONCURRENT - readable = initial; - tv.tv_sec = tv.tv_usec = 0; - - if (msgs_queued()) { -#if 1 - zdbug((LOG_DEBUG, "brl msgqued")); -#endif - fd_ready = 1; - } else - fd_ready = select(srv_socket + 1, &readable, - (fd_set *)0, - (fd_set *)0, &tv); - /* - * if there are packets to be processed, do them. - * We needn't worry about locking since we don't - * know what's coming our way. - */ - if (fd_ready > 0) { -#if 1 - zdbug((LOG_DEBUG, "brl fdready")); -#endif - handle_packet(); -#ifdef notdef - if (cancel_outgoing_dump) { - cancel_outgoing_dump = 0; - return EWOULDBLOCK; /* maybe in a warped sort - of way */ - } -#endif - } else if (fd_ready < 0) - syslog(LOG_ERR, "brl select: %m"); -#endif /* CONCURRENT */ - len = sizeof(packet); - if ((retval = get_packet(packet, len, &len)) != ZERR_NONE) { - syslog(LOG_ERR, "brl get pkt: %s", - error_message(retval)); - return(retval); - } + /* do the inverse of bdump_send_loop, registering stuff on the fly */ + while (1) { + if (packets_waiting()) { + /* A non-braindump packet is waiting; handle it. */ + bdumping = 0; + bdump_concurrent = 1; + handle_packet(); + bdump_concurrent = 0; + bdumping = 1; + } + len = sizeof(packet); + retval = get_packet(packet, len, &len); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "brl get pkt: %s", error_message(retval)); + return retval; + } - if ((retval = ZParseNotice(packet, len, ¬ice)) != ZERR_NONE) { - syslog(LOG_ERR, "brl notice parse: %s", - error_message(retval)); - return(retval); - } + retval = ZParseNotice(packet, len, ¬ice); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "brl notice parse: %s", error_message(retval)); + return retval; + } #if defined (DEBUG) - if (zdebug) { - char buf[4096]; - - (void) sprintf(buf, - "bdump:%s '%s' '%s' '%s' '%s' '%s'", - ZNoticeKinds[(int) notice.z_kind], - notice.z_class, - notice.z_class_inst, - notice.z_opcode, - notice.z_sender, - notice.z_recipient); - syslog(LOG_DEBUG, buf); - } + if (zdebug) { + char buf[4096]; + + sprintf(buf, "bdump:%s '%s' '%s' '%s' '%s' '%s'", + ZNoticeKinds[(int) notice.z_kind], notice.z_class, + notice.z_class_inst, notice.z_opcode, notice.z_sender, + notice.z_recipient); + syslog(LOG_DEBUG, buf); + } #endif /* DEBUG */ - if (notice.z_kind == HMCTL) { - /* host register */ - if ((retval = extract_sin(¬ice, ¤t_who)) != - ZERR_NONE) { - syslog(LOG_ERR, "brl hmctl sin: %s", - error_message(retval)); - return(retval); - } - who_valid = 1; - /* 1 = tell it we are authentic */ - if ((retval = hostm_dispatch(¬ice, 1, - ¤t_who, server)) - != ZERR_NONE) { - syslog(LOG_ERR,"brl hm_disp failed: %s", - error_message(retval)); - return(retval); - } - } else if (!strcmp(notice.z_opcode, ADMIN_DONE)) { - /* end of brain dump */ - return(ZERR_NONE); - } else if (!who_valid) { - syslog(LOG_ERR, "brl: no current host"); - return(ZSRV_HNOTFOUND); - } else if (!strcmp(notice.z_class, LOGIN_CLASS)) { - /* 1 = tell it we are authentic */ - if ((retval = ulogin_dispatch(¬ice, 1, - ¤t_who, server)) - != ZERR_NONE) { - syslog(LOG_ERR, "brl ul_disp failed: %s", - error_message(retval)); - return(retval); - } - } else if (!strcmp(notice.z_opcode, ADMIN_NEWCLT)) { - /* register a new client */ - notice.z_port = htons((u_short)atoi(notice.z_message)); - if (ntohs(notice.z_port) == 0) { - /* this is a bogus client from an older rev. - server, so we just flush it. */ - syslog(LOG_ERR, "brl flushing %s/0", - inet_ntoa(current_who.sin_addr)); - flushing_subs = 1; - continue; /* while loop */ - } - flushing_subs = 0; - if ((retval = client_register(¬ice, - ¤t_who, - &client, - server, - 0)) != ZERR_NONE) { - syslog(LOG_ERR,"brl register failed: %s", - error_message(retval)); - return(retval); - } -#ifdef KERBEROS - (void) memset((caddr_t) client->zct_cblock, 0, - sizeof(C_Block)); - if (*notice.z_class_inst) { - /* a C_Block is there */ - cp = notice.z_message + - strlen(notice.z_message) + 1; - retval = ZReadAscii(cp,strlen(cp), - cblock, sizeof(C_Block)); - if (retval != ZERR_NONE) { - syslog(LOG_ERR,"brl bad cblk read: %s (%s)", - error_message(retval), - cp); - } else { + if (notice.z_num_other_fields >= 1) { + retval = ZReadAscii(notice.z_other_fields[0], + strlen(notice.z_other_fields[0]), + (unsigned char *) &who.sin_addr, + sizeof(struct in_addr)); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "brl zreadascii failed: %s", + error_message(retval)); + return retval; + } + } else { + who.sin_addr.s_addr = notice.z_sender_addr.s_addr; + } + who.sin_family = AF_INET; + who.sin_port = notice.z_port; + + if (strcmp(notice.z_opcode, ADMIN_DONE) == 0) { + /* end of brain dump */ + return ZERR_NONE; + } else if (strcmp(notice.z_opcode, ADMIN_NEWREALM) == 0) { + /* get a realm from the message */ + realm = realm_get_realm_by_name(notice.z_message); + if (!realm) + return(ZERR_NONE); + } else if (strcmp(notice.z_class, LOGIN_CLASS) == 0) { + /* 1 = tell it we are authentic */ + retval = ulogin_dispatch(¬ice, 1, &who, server); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "brl ul_disp failed: %s", + error_message(retval)); + return retval; + } + } else if (strcmp(notice.z_opcode, ADMIN_NEWCLT) == 0) { + /* a new client */ + notice.z_port = htons((u_short) atoi(notice.z_message)); + retval = client_register(¬ice, &who.sin_addr, &client, 0); + if (retval != ZERR_NONE) { + syslog(LOG_ERR,"brl failed: %s", error_message(retval)); + return retval; + } +#ifdef ZEPHYR_USES_KERBEROS + memset(client->session_key, 0, sizeof(C_Block)); + if (*notice.z_class_inst) { + /* a C_Block is there */ + cp = notice.z_message + strlen(notice.z_message) + 1; + retval = ZReadAscii(cp, strlen(cp), cblock, sizeof(C_Block)); + if (retval != ZERR_NONE) { + syslog(LOG_ERR,"brl bad cblk read: %s (%s)", + error_message(retval), cp); + } else { #ifdef NOENCRYPTION - memcpy((caddr_t)cblock, - (caddr_t)client->zct_cblock, - sizeof(C_Block)); + memcpy(cblock, client->session_key, sizeof(C_Block)); #else - des_ecb_encrypt(cblock, client->zct_cblock, - serv_ksched.s, DES_DECRYPT); + des_ecb_encrypt(cblock, client->session_key, serv_ksched.s, + DES_DECRYPT); #endif - } - } -#endif /* KERBEROS */ - } else if (!strcmp(notice.z_opcode, CLIENT_SUBSCRIBE)) { - if (flushing_subs) - continue; /* while loop */ - /* a subscription packet */ - if (!client) { - syslog(LOG_ERR, "brl no client"); - return(ZSRV_NOCLT); - } - if ((retval = subscr_subscribe(client, ¬ice)) != ZERR_NONE) { - syslog(LOG_WARNING, "brl subscr failed: %s", - error_message(retval)); - return(retval); - } - } else { - syslog(LOG_ERR, "brl bad opcode %s",notice.z_opcode); - return(ZSRV_UNKNOWNOPCODE); } + } +#endif /* ZEPHYR_USES_KERBEROS */ + } else if (strcmp(notice.z_opcode, CLIENT_SUBSCRIBE) == 0) { + /* a subscription packet */ + if (!client) { + syslog(LOG_ERR, "brl no client"); + return ZSRV_NOCLT; + } + retval = subscr_subscribe(client, ¬ice); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "brl subscr failed: %s", + error_message(retval)); + return retval; + } + } else if (strcmp(notice.z_opcode, REALM_SUBSCRIBE) == 0) { + /* add a subscription for a realm */ + if (!realm) { + syslog(LOG_ERR, "brl no realm"); + return(ZSRV_NORLM); + } + retval = subscr_realm(realm, ¬ice); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "brl subscr failed: %s", + error_message(retval)); + return retval; + } + } else { + syslog(LOG_ERR, "brl bad opcode %s",notice.z_opcode); + return ZSRV_UNKNOWNOPCODE; } + } } - + /* - * Send all the state from server to the peer. + * Send all the state to the peer. */ - + static Code_t -bdump_send_loop(server, vers) - ZServerDesc_t *server; - char *vers; +bdump_send_loop(server) + Server *server; { - register ZHostList_t *host; - register ZClientList_t *clist; - Code_t retval; -#ifdef CONCURRENT - fd_set readable, initial; - int fd_ready; - struct timeval tv; -#endif /* CONCURRENT */ - + Code_t retval; + #if 1 - zdbug((LOG_DEBUG, "bdump send loop")); -#endif - - -#ifdef CONCURRENT - FD_ZERO(&initial); - FD_SET(srv_socket, &initial); -#endif /* CONCURRENT */ - - for (host = server->zs_hosts->q_forw; - host != server->zs_hosts; - host = host->q_forw) { - /* for each host */ -#ifdef CONCURRENT - host->zh_locked = 1; - - readable = initial; - tv.tv_sec = tv.tv_usec = 0; - - if (msgs_queued()) - fd_ready = 1; - else - fd_ready = select(srv_socket + 1, &readable, - (fd_set *)0, - (fd_set *)0, &tv); - /* - * if there are packets to be processed, do them. - * locking the host above insures nothing we are working on - * gets trashed. - */ - if (fd_ready > 0) { - handle_packet(); -#ifdef notdef - if (cancel_outgoing_dump) { - cancel_outgoing_dump = 0; - return EWOULDBLOCK; - } -#endif - } else if (fd_ready < 0) - syslog(LOG_ERR, "bsl select: %m"); - -#endif /* CONCURRENT */ - if ((retval = send_host_register(host)) != ZERR_NONE) { - host->zh_locked = 0; - return(retval); - } - if ((retval = uloc_send_locations(host, vers)) != ZERR_NONE) { - host->zh_locked = 0; - return(retval); - } - if (!host->zh_clients) { - host->zh_locked = 0; - continue; - } - for (clist = host->zh_clients->q_forw; - clist != host->zh_clients; - clist = clist->q_forw) { - /* for each client */ - if (!clist->zclt_client->zct_subs) { - host->zh_locked = 0; - continue; - } - if ((retval = subscr_send_subs(clist->zclt_client, - vers)) != ZERR_NONE) { - host->zh_locked = 0; - return(retval); - } - } - host->zh_locked = 0; - } - retval = send_done(); - return(retval); -} - -/* - * Send a host boot packet to the other server - */ - -static Code_t -send_host_register(host) - ZHostList_t *host; -{ - char buf[512], *addr, *lyst[2]; - Code_t retval; - -#if 0 - zdbug((LOG_DEBUG, "bdump_host_register")); + zdbug((LOG_DEBUG, "bdump send loop")); #endif - addr = inet_ntoa(host->zh_addr.sin_addr); - (void) sprintf(buf, "%d", ntohs(host->zh_addr.sin_port)); - lyst[0] = addr; - lyst[1] = buf; - - /* myname is the hostname */ - retval = bdump_send_list_tcp (HMCTL, (int) bdump_sin.sin_port, - ZEPHYR_CTL_CLASS, ZEPHYR_CTL_HM, - HM_BOOT, myname, "", lyst, 2); - if (retval != ZERR_NONE) - syslog(LOG_ERR, "shr send: %s",error_message(retval)); - return(retval); + + retval = uloc_send_locations(); + if (retval != ZERR_NONE) + return retval; + retval = client_send_clients(); + if (retval != ZERR_NONE) + return retval; + retval = realm_send_realms(); + if (retval != ZERR_NONE) + return retval; + return send_done(); } - + /* * Send a sync indicating end of this host */ - + static Code_t send_done() { - Code_t retval; + Code_t retval; #if 1 - zdbug((LOG_DEBUG, "send_done")); + zdbug((LOG_DEBUG, "send_done")); #endif - retval = send_normal_tcp(SERVACK, bdump_sin.sin_port, - ZEPHYR_ADMIN_CLASS, "", ADMIN_DONE, myname, - "", (char *) NULL, 0); - return(retval); + retval = send_normal_tcp(SERVACK, bdump_sin.sin_port, ZEPHYR_ADMIN_CLASS, + "", ADMIN_DONE, myname, "", NULL, 0); + return retval; } - - + + /* * Send a list off as the specified notice */ - + static Code_t send_list(kind, port, class_name, inst, opcode, sender, recip, lyst, num) - ZNotice_Kind_t kind; - int port; - char *class_name; - char *inst; - char *opcode; - char *sender; - char *recip; - char **lyst; - int num; + ZNotice_Kind_t kind; + int port, num; + char *class_name, *inst, *opcode, *sender, *recip, **lyst; { - ZNotice_t notice; - register ZNotice_t *pnotice; /* speed hack */ - char *pack; - int packlen; - Code_t retval; - - pnotice = ¬ice; - - pnotice->z_kind = kind; - - pnotice->z_port = port; - pnotice->z_class = class_name; - pnotice->z_class_inst = inst; - pnotice->z_opcode = opcode; - pnotice->z_sender = sender; - pnotice->z_recipient = recip; - pnotice->z_default_format = ""; - pnotice->z_num_other_fields = 0; + ZNotice_t notice; + char *pack; + int packlen; + Code_t retval; + + notice.z_kind = kind; + notice.z_port = port; + notice.z_class = class_name; + notice.z_class_inst = inst; + notice.z_opcode = opcode; + notice.z_sender = sender; + notice.z_recipient = recip; + notice.z_default_format = ""; + notice.z_num_other_fields = 0; - if ((retval = ZFormatNoticeList(pnotice, lyst, num, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) { - syslog(LOG_WARNING, "sl format: %s", error_message(retval)); - return(retval); - } + retval = ZFormatNoticeList(¬ice, lyst, num, &pack, &packlen, ZNOAUTH); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "sl format: %s", error_message(retval)); + return retval; + } - if ((retval = ZSendPacket(pack, packlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "sl xmit: %s", error_message(retval)); - xfree(pack); /* free allocated storage */ - return(retval); - } - xfree(pack); /* free allocated storage */ - return(ZERR_NONE); + retval = ZSendPacket(pack, packlen, 0); + if (retval != ZERR_NONE) + syslog(LOG_WARNING, "sl xmit: %s", error_message(retval)); + free(pack); + return retval; } - + /* * Send a message off as the specified notice, via TCP */ - + static Code_t send_normal_tcp(kind, port, class_name, inst, opcode, sender, recip, message, len) - ZNotice_Kind_t kind; - int port; - char *class_name; - char *inst; - char *opcode; - char *sender; - char *recip; - char *message; - int len; + ZNotice_Kind_t kind; + int port, len; + char *class_name, *inst, *opcode, *sender, *recip, *message; { - ZNotice_t notice; - register ZNotice_t *pnotice; /* speed hack */ - char *pack; - int packlen, count; - Code_t retval; - u_short length; - - pnotice = ¬ice; - - pnotice->z_kind = kind; + ZNotice_t notice; + char *pack; + int packlen, count; + Code_t retval; + u_short length; + + notice.z_kind = kind; + notice.z_port = port; + notice.z_class = class_name; + notice.z_class_inst = inst; + notice.z_opcode = opcode; + notice.z_sender = sender; + notice.z_recipient = recip; + notice.z_default_format = ""; + notice.z_message = message; + notice.z_message_len = len; + notice.z_num_other_fields = 0; + + retval = ZFormatNotice(¬ice, &pack, &packlen, ZNOAUTH); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "sn format: %s", error_message(retval)); + return retval; + } - pnotice->z_port = port; - pnotice->z_class = class_name; - pnotice->z_class_inst = inst; - pnotice->z_opcode = opcode; - pnotice->z_sender = sender; - pnotice->z_recipient = recip; - pnotice->z_default_format = ""; - pnotice->z_message = message; - pnotice->z_message_len = len; - pnotice->z_num_other_fields = 0; + length = htons((u_short) packlen); - if ((retval = ZFormatNotice(pnotice, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) { - syslog(LOG_WARNING, "sn format: %s", error_message(retval)); - return(retval); + count = net_write(output, (char *) &length, sizeof(length)); + if (count != sizeof(length)) { + if (count < 0) { + syslog(LOG_WARNING, "snt xmit/len: %m"); + free(pack); + return errno; + } else { + syslog(LOG_WARNING, "snt xmit: %d vs %d",sizeof(length),count); + free(pack); + return ZSRV_LEN; } - - length = htons((u_short) packlen); - - if ((count = net_write(output, (caddr_t) &length, sizeof(length))) != sizeof(length)) { - if (count < 0) { - syslog(LOG_WARNING, "snt xmit/len: %m"); - xfree(pack); /* free allocated storage */ - return(errno); - } else { - syslog(LOG_WARNING, "snt xmit: %d vs %d",sizeof(length),count); - xfree(pack); /* free allocated storage */ - return(ZSRV_LEN); - } + } + count = net_write(output, pack, packlen); + if (count != packlen) { + if (count < 0) { + syslog(LOG_WARNING, "snt xmit: %m"); + free(pack); + return errno; + } else { + syslog(LOG_WARNING, "snt xmit: %d vs %d",packlen, count); + free(pack); + return ZSRV_LEN; } - if ((count = net_write(output, pack, packlen)) != packlen) - if (count < 0) { - syslog(LOG_WARNING, "snt xmit: %m"); - xfree(pack); /* free allocated storage */ - return(errno); - } else { - syslog(LOG_WARNING, "snt xmit: %d vs %d",packlen, count); - xfree(pack); /* free allocated storage */ - return(ZSRV_LEN); - } - xfree(pack); /* free allocated storage */ - return(ZERR_NONE); + } + free(pack); + return ZERR_NONE; } - + /* * get a packet from the TCP socket * return 0 if successful, error code else */ - + static Code_t get_packet(packet, len, retlen) - caddr_t packet; - int len; - int *retlen; + void *packet; + int len; + int *retlen; { - u_short length; - int result; + u_short length; + int result; - if ((result = net_read(input, (caddr_t) &length, sizeof(u_short))) < sizeof(short)) { - if (result < 0) - return(errno); - else { - syslog(LOG_ERR, "get_pkt len: %d vs %d (%m)", result, sizeof(short)); - return(ZSRV_LEN); - } + result = net_read(input, (char *) &length, sizeof(u_short)); + if (result < sizeof(short)) { + if (result < 0) { + return errno; + } else { + syslog(LOG_ERR, "get_pkt len: %d vs %d (%m)", result, + sizeof(short)); + return ZSRV_LEN; } + } - length = ntohs(length); - if (len < length) - return(ZSRV_BUFSHORT); - if ((result = net_read(input, packet, (int) length)) < length) { - if (result < 0) - return(errno); - else { - syslog(LOG_ERR, "get_pkt: %d vs %d (%m)",result, length); - return(ZSRV_LEN); - } + length = ntohs(length); + if (len < length) + return ZSRV_BUFSHORT; + result = net_read(input, packet, (int) length); + if (result < length) { + if (result < 0) { + return errno; + } else { + syslog(LOG_ERR, "get_pkt: %d vs %d (%m)", result, length); + return ZSRV_LEN; } - *retlen = (int) length; - return(ZERR_NONE); + } + *retlen = length; + return ZERR_NONE; } - + static Code_t extract_sin(notice, target) - ZNotice_t *notice; - struct sockaddr_in *target; + ZNotice_t *notice; + struct sockaddr_in *target; { - register char *cp = notice->z_message; - char *buf; + char *cp = notice->z_message; + char *buf; - buf = cp; - if (!notice->z_message_len || *buf == '\0') { + buf = cp; + if (!notice->z_message_len || *buf == '\0') { #if 0 - zdbug((LOG_DEBUG,"no addr")); + zdbug((LOG_DEBUG,"no addr")); #endif - return(ZSRV_PKSHORT); - } - target->sin_addr.s_addr = inet_addr(cp); + return ZSRV_PKSHORT; + } + target->sin_addr.s_addr = inet_addr(cp); - cp += (strlen(cp) + 1); /* past the null */ - if ((cp >= notice->z_message + notice->z_message_len) - || (*cp == '\0')) { + cp += (strlen(cp) + 1); /* past the null */ + if ((cp >= notice->z_message + notice->z_message_len) || (*cp == '\0')) { #if 0 - zdbug((LOG_DEBUG, "no port")); + zdbug((LOG_DEBUG, "no port")); #endif - return(ZSRV_PKSHORT); - } - target->sin_port = htons((u_short) atoi(cp)); - target->sin_family = AF_INET; - return(ZERR_NONE); + return(ZSRV_PKSHORT); + } + target->sin_port = htons((u_short) atoi(cp)); + target->sin_family = AF_INET; + return ZERR_NONE; } - + static int net_read(f, buf, len) - FILE *f; - register char *buf; - register int len; + FILE *f; + char *buf; + int len; { int cc, len2 = 0; fflush (output); do { errno = 0; - cc = fread (buf, 1, len, f); + cc = fread(buf, 1, len, f); if (cc == 0) return -1; buf += cc; @@ -1591,15 +1154,15 @@ net_read(f, buf, len) } while (len > 0); return len2; } - + static int net_write(f, buf, len) - FILE *f; - register char *buf; - int len; + FILE *f; + char *buf; + int len; { int cc; - register int wrlen = len; + int wrlen = len; do { cc = fwrite (buf, 1, wrlen, f); if (cc == 0) @@ -1613,7 +1176,7 @@ net_write(f, buf, len) static int setup_file_pointers () { - int fd; + int fd; input = fdopen (live_socket, "r"); if (!input) diff --git a/server/class.c b/server/class.c index b70bf4e..b4c46d8 100644 --- a/server/class.c +++ b/server/class.c @@ -12,41 +12,40 @@ */ #include <zephyr/mit-copyright.h> +#include "zserver.h" /* includes zephyr/zephyr.h */ +#include <assert.h> #if !defined (lint) && !defined (SABER) -static char rcsid_class_c[] = - "$Id$"; +static const char rcsid_class_c[] = +"$Id$"; #endif -#include "zserver.h" /* includes zephyr/zephyr.h */ - -#include <ctype.h> /* for isupper, tolower */ - /* * Class manager subsystem. * * * External functions are: * - * Code_t triplet_register(client, subs) + * Code_t triplet_register(client, subs, realm) * - * Code_t triplet_deregister(client, subs) + * Code_t triplet_deregister(client, subs, realm) * - * ZClientList_t *triplet_lookup(subs) - * ZClient_t *client; - * ZSubscr_t *subs; + * Client *triplet_lookup(subs) + * Client *client; + * Destlist *subs; * - * ZAcl_t *class_get_acl(ZString class_name) + * Acl *class_get_acl(class_name) + * String *class_name; * * Code_t class_restrict(class_name, acl) * char *class_name; - * ZAcl_t *acl; + * Acl *acl; * * Code_t class_setup_restricted(class_name, acl) * char *class_name; - * ZAcl_t *acl; + * Acl *acl; * - * and several ZDestination methods. + * and several Destination methods. */ /* @@ -56,7 +55,7 @@ static char rcsid_class_c[] = * name (which hashes into the bucket associated with this list) and a * doubly linked list of clients which are interested in this class. * The data pointed to by these clients is owned by other modules. Care - * must be taken by the caller not to register a free()'d client + * must be taken by the caller not to a free()'d client * structure. * * If any hash bucket is empty, the pointer is null. @@ -71,26 +70,23 @@ static char rcsid_class_c[] = /* Private variables */ #define EMPTY_CLASS 2000 +#define ALLOC_OFFSET 8 /* Allocate 32 bytes less than a power of 2. */ +#define ALLOC_INIT 8 /* Initial number of subscriptions. */ + #define HASHSIZE 1023 #define HASHVAL(c, i, r) (((c)->hash_val ^ (i)->hash_val ^ (r)->hash_val) \ % HASHSIZE) #define DEST_HASHVAL(dest) HASHVAL((dest).classname, (dest).inst, (dest).recip) -static ZTriplet_t *class_bucket[HASHSIZE]; /* the hash table of pointers */ - +static Triplet *triplet_bucket[HASHSIZE]; /* the hash table of pointers */ -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -static Code_t remove_client P((ZTriplet_t *ptr, ZClient_t *client)); -static Code_t insert_client P((ZTriplet_t *ptr, ZClient_t *client)); -static ZClientList_t *client_alloc P((ZClient_t *client)); -static ZTriplet_t *triplet_alloc P((ZSTRING *classname, ZSTRING *inst, - ZSTRING *recipient)); -static void free_class P((ZTriplet_t *)); +static Code_t remove_client __P((Triplet *triplet, Client *client, + Realm *realm)); +static Code_t insert_client __P((Triplet *triplet, Client *client, + Realm *realm)); +static Triplet *triplet_alloc __P((String *classname, String *inst, + String *recipient)); +static void free_triplet __P((Triplet *)); /* public routines */ @@ -102,169 +98,112 @@ static void free_class P((ZTriplet_t *)); * been case-sensitive in the recipient string. In most cases, a * failed match will fail on the classname or instance, and a successful * match will succeed on the (d1->recip == d2->recip) check, so this - * shouldn't affect performance. Note that this invalidates the overall - * hash value check, which was of dubious value to start with. + * shouldn't affect performance. */ int ZDest_eq(d1, d2) - ZDestination *d1, *d2; + Destination *d1, *d2; { - return((d1->classname == d2->classname) && - (d1->inst == d2->inst) && - (d1->recip == d2->recip || - strcasecmp(d1->recip->string, d2->recip->string) == 0)); + return((d1->classname == d2->classname) && + (d1->inst == d2->inst) && + (d1->recip == d2->recip || + strcasecmp(d1->recip->string, d2->recip->string) == 0)); } -/* register the client as interested in a triplet */ +/* the client as interested in a triplet */ Code_t -triplet_register(client, dest) - ZClient_t *client; - ZDestination *dest; +triplet_register(client, dest, realm) + Client *client; + Destination *dest; + Realm *realm; { - register ZTriplet_t *ptr, *ptr2; - unsigned long hashval; - - hashval = DEST_HASHVAL(*dest); - - if (!(ptr = class_bucket[hashval])) { - /* not registered */ - - ptr = triplet_alloc(dest->classname, dest->inst, dest->recip); - if (!ptr) - return(ENOMEM); - - /* allocate the head of the bucket */ - - if (!(ptr2 = (ZTriplet_t *) xmalloc(sizeof(ZTriplet_t)))) - return(ENOMEM); - - ptr2->zct_clientlist = 0; - ptr2->zct_acl = 0; - ptr2->q_forw = ptr; - ptr2->q_back = ptr; - ptr->q_forw = ptr2; - ptr->q_back = ptr2; - - class_bucket[hashval] = ptr2; - return(insert_client(ptr, client)); - - } else { - for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw) { - /* walk down the list, looking for a match */ - if (ZDest_eq(&ptr2->zct_dest,dest)) - return(insert_client(ptr2, client)); - } + Triplet *triplet; + unsigned long hashval; - /* fell off the end, no match */ - ptr2 = triplet_alloc(dest->classname, dest->inst, dest->recip); - if (!ptr2) - return(ENOMEM); + hashval = DEST_HASHVAL(*dest); + for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) { + if (ZDest_eq(&triplet->dest, dest)) + return insert_client(triplet, client, realm); + } - xinsque(ptr2, ptr); /* insert new class into hash bucket */ - return(insert_client(ptr2, client)); - } + /* Triplet not present in hash table, insert it. */ + triplet = triplet_alloc(dest->classname, dest->inst, dest->recip); + LIST_INSERT(&triplet_bucket[hashval], triplet); + return insert_client(triplet, client, realm); } /* dissociate client from the class, garbage collecting if appropriate */ Code_t -triplet_deregister(client, dest) - ZClient_t *client; - ZDestination *dest; +triplet_deregister(client, dest, realm) + Client *client; + Destination *dest; + Realm *realm; { - register ZTriplet_t *ptr, *ptr2; - int retval = -1; - unsigned long hashval; + Triplet *triplet; + int retval; + unsigned long hashval; - hashval = DEST_HASHVAL(*dest); -#if 0 - zdbug((LOG_DEBUG, "class_dereg: %s %s", dest->classname->string, - dest->inst->string)); -#endif - ptr = class_bucket[hashval]; - if (!ptr) - /* no such class to deregister */ - return(ZSRV_BADASSOC); - - for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw) { - /* walk down the list, looking for a match */ - if (ZDest_eq(&ptr2->zct_dest,dest)) { - retval = remove_client(ptr2, client); - if (retval == EMPTY_CLASS) { #if 0 - zdbug((LOG_DEBUG,"empty class")); + zdbug((LOG_DEBUG, "class_dereg: %s %s", dest->classname->string, + dest->inst->string)); #endif - /* Don't free up restricted classes. */ - if (ptr2->zct_acl) - return(ZERR_NONE); - else { - xremque(ptr2); - free_class(ptr2); - return(ZERR_NONE); - } - } - /* if not EMPTY_CLASS, it's either ZSRV_BADASSOC - (not found) or ZERR_NONE (found and removed), - so break */ - break; - } + hashval = DEST_HASHVAL(*dest); + for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) { + if (ZDest_eq(&triplet->dest, dest)) { + retval = remove_client(triplet, client, realm); + if (retval != ZERR_NONE) + return retval; + if (*triplet->clients == NULL && !triplet->acl) { + LIST_DELETE(triplet); + free_triplet(triplet); + } + return ZERR_NONE; } - - /* fell off: either client not found or client found - and removed, retval contains the result */ - return(retval); + } + return(ZSRV_BADASSOC); } - + /* return a linked list of what clients are interested in this triplet */ -ZClientList_t * +Client ** triplet_lookup(dest) - ZDestination *dest; + Destination *dest; { - register ZTriplet_t *class, *p; - unsigned long hashval; - - hashval = DEST_HASHVAL(*dest); - p = class_bucket[hashval]; - if (p == NULLZT) - return NULLZCLT; - - /* Go search the list for the class */ - for (class = p->q_forw; class != p; class = class->q_forw) { - /* walk down the list, looking for a match */ - if (ZDest_eq(&class->zct_dest,dest)) - return class->zct_clientlist; - } - return NULLZCLT; + Triplet *triplet; + unsigned long hashval; + + hashval = DEST_HASHVAL(*dest); + for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) { + if (ZDest_eq(&triplet->dest, dest)) + return triplet->clients; + } + return NULL; } /* - * return the acl structure associated with class, or NULLZACLT if there is + * return the acl structure associated with class, or NULL if there is * no such acl struct */ -ZAcl_t * +Acl * class_get_acl(class_name) - ZSTRING *class_name; + String *class_name; { - register ZTriplet_t *ptr, *ptr2; - unsigned long hashval; - - hashval = HASHVAL(class_name, empty, empty); - if (!(ptr = class_bucket[hashval])) - return(NULLZACLT); - - /* walk down the list, looking for a match */ - for (ptr2 = ptr->q_back; ptr2 != ptr; ptr2 = ptr2->q_back) - if ((ptr2->zct_dest.classname == class_name) && - (ptr2->zct_dest.inst == empty) && - (ptr2->zct_dest.recip == empty)) - return(ptr2->zct_acl); - - /* fell off the end, no match ==> not restricted */ - return(NULLZACLT); + Triplet *triplet; + unsigned long hashval; + + hashval = HASHVAL(class_name, empty, empty); + for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) { + if (triplet->dest.classname == class_name && + triplet->dest.inst == empty && triplet->dest.recip == empty) + return triplet->acl; + } + + /* No acl found, not restricted. */ + return NULL; } /* @@ -275,35 +214,28 @@ class_get_acl(class_name) Code_t class_restrict(class_name, acl) - char *class_name; - ZAcl_t *acl; + char *class_name; + Acl *acl; { - register ZTriplet_t *ptr, *ptr2; - ZSTRING *d; - unsigned long hashval; - - d = make_zstring(class_name,1); - hashval = HASHVAL(d, empty, empty); - - if (!(ptr = class_bucket[hashval])) { - free_zstring(d); - return(ZSRV_NOCLASS); + Triplet *triplet; + String *d; + unsigned long hashval; + + d = make_string(class_name,1); + hashval = HASHVAL(d, empty, empty); + for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) { + if (triplet->dest.classname == d && triplet->dest.inst == empty && + triplet->dest.recip == empty) { + if (triplet->acl) + return ZSRV_CLASSRESTRICTED; + triplet->acl = acl; + free_string(d); + return ZERR_NONE; } - for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw) - /* walk down the list, looking for a match */ - if ((ptr2->zct_dest.classname == d) && - (ptr2->zct_dest.inst == empty) && - (ptr2->zct_dest.recip == empty)) { - if (ptr2->zct_acl) - return ZSRV_CLASSRESTRICTED; - ptr2->zct_acl = acl; - free_zstring(d); - return(ZERR_NONE); - } + } - /* fell off the end, no match */ - free_zstring(d); - return(ZSRV_NOCLASS); + free_string(d); + return ZSRV_NOCLASS; } /* @@ -311,132 +243,100 @@ class_restrict(class_name, acl) * structure acl. return ZERR_NONE if no error, or ZSRV_CLASSXISTS * if the class is already registered, or ENOMEM in case of malloc failure. */ - + Code_t class_setup_restricted(class_name, acl) - char *class_name; - ZAcl_t *acl; + char *class_name; + Acl *acl; { - register ZTriplet_t *ptr, *ptr2; - ZSTRING *d; - unsigned long hashval; - - d = make_zstring(class_name,1); - hashval = HASHVAL(d, empty, empty); - - if (!(ptr = class_bucket[hashval])) { - /* not registered */ - - ptr = triplet_alloc(d,empty,empty); - if (!ptr) - return(ENOMEM); - - ptr->zct_acl = acl; - - /* allocate the head of the bucket */ - ptr2 = (ZTriplet_t *) xmalloc(sizeof(ZTriplet_t)); - if (!ptr2) - return(ENOMEM); - - ptr2->q_forw = ptr; - ptr2->q_back = ptr; - ptr->q_forw = ptr2; - ptr->q_back = ptr2; - - class_bucket[hashval] = ptr2; - free_zstring(d); - return(ZERR_NONE); - } else { - for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw) - /* walk down the list, looking for a match */ - if ((ptr2->zct_dest.classname == d) && - (ptr2->zct_dest.inst == empty) && - (ptr2->zct_dest.recip == empty)) { - free_zstring(d); - return(ZSRV_CLASSXISTS); - } - if (!(ptr2 = triplet_alloc(d,empty,empty))) { - free_zstring(d); - return(ENOMEM); - } - - free_zstring(d); - ptr2->zct_acl = acl; - xinsque(ptr2, ptr); - return(ZERR_NONE); + Triplet *triplet; + String *d; + unsigned long hashval; + + d = make_string(class_name,1); + hashval = HASHVAL(d, empty, empty); + for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) { + if (triplet->dest.classname == d && triplet->dest.inst == empty && + triplet->dest.recip == d) { + free_string(d); + return ZSRV_CLASSXISTS; } + } + + /* Triplet not present in hash table, insert it. */ + triplet = triplet_alloc(d, empty, empty); + free_string(d); + if (!triplet) + return ENOMEM; + triplet->acl = acl; + LIST_INSERT(&triplet_bucket[hashval], triplet); + return ZERR_NONE; } /* private routines */ /* allocate space for a class structure */ -static ZTriplet_t * +static Triplet * triplet_alloc(classname,inst,recipient) - ZSTRING *classname; - ZSTRING *inst; - ZSTRING *recipient; + String *classname, *inst, *recipient; { - register ZTriplet_t *ptr; - ZClientList_t *clist; - - if (!(ptr = (ZTriplet_t *) xmalloc(sizeof(ZTriplet_t)))) - return(NULLZT); - - ptr->q_forw = ptr->q_back = ptr; - ptr->zct_dest.classname = dup_zstring(classname); - ptr->zct_dest.inst = dup_zstring(inst); - ptr->zct_dest.recip = dup_zstring(recipient); - - if (!(clist = (ZClientList_t *) xmalloc (sizeof (ZClientList_t)))) { - xfree(ptr); - return(NULLZT); - } - clist->q_forw = clist->q_back = clist; - ptr->zct_clientlist = clist; - ptr->zct_acl = NULLZACLT; + Triplet *triplet; + Client *clist; - return (ptr); -} - -/* allocate space for a client entry */ - -static ZClientList_t * -client_alloc(client) - ZClient_t *client; -{ - register ZClientList_t *ptr; - if (!(ptr = (ZClientList_t *) xmalloc(sizeof(ZClientList_t)))) - return(NULLZCLT); + triplet = (Triplet *) malloc(sizeof(Triplet)); + if (!triplet) + return NULL; - ptr->q_forw = ptr->q_back = ptr; - ptr->zclt_client = client; + triplet->dest.classname = dup_string(classname); + triplet->dest.inst = dup_string(inst); + triplet->dest.recip = dup_string(recipient); + triplet->clients = NULL; + triplet->acl = NULL; - return(ptr); + return triplet; } /* insert a client into the list associated with the class *ptr */ static Code_t -insert_client(ptr, client) - ZTriplet_t *ptr; - ZClient_t *client; +insert_client(triplet, client, realm) + Triplet *triplet; + Client *client; + Realm *realm; { - register ZClientList_t *listp, *clist; - - for (clist = ptr->zct_clientlist->q_forw; - clist != ptr->zct_clientlist; - clist = clist->q_forw) { - /* don't duplicate */ - if (clist->zclt_client == client) - return(ZSRV_CLASSXISTS); + Client **clientp, **newclients; + int new_size; + + if (triplet->clients) { + /* Avoid duplication. */ + for (clientp = triplet->clients; *clientp; clientp++) { + if (*clientp == client || (realm && (*clientp)->realm == realm)) + return ZSRV_CLASSXISTS; } - if (!(listp = client_alloc(client))) - return(ENOMEM); + if (clientp + 1 - triplet->clients >= triplet->clients_size) { + new_size = triplet->clients_size * 2 + ALLOC_OFFSET; + newclients = (Client **) realloc(triplet->clients, + new_size * sizeof(Client *)); + if (newclients == NULL) + return ENOMEM; + clientp = newclients + (clientp - triplet->clients); + triplet->clients = newclients; + triplet->clients_size = new_size; + } + } else { + /* Allocate an initial list of client pointers. */ + triplet->clients = (Client **) malloc(ALLOC_INIT * sizeof(Client *)); + if (triplet->clients == NULL) + return ENOMEM; + triplet->clients_size = ALLOC_INIT; + clientp = triplet->clients; + } - xinsque(listp, ptr->zct_clientlist); - return(ZERR_NONE); + *clientp = client; + clientp[1] = NULL; + return ZERR_NONE; } /* @@ -444,70 +344,58 @@ insert_client(ptr, client) * collecting if appropriate */ -static Code_t remove_client(ptr, client) - ZTriplet_t *ptr; - ZClient_t *client; +static Code_t remove_client(triplet, client, realm) + Triplet *triplet; + Client *client; + Realm *realm; { - register ZClientList_t *listp = ptr->zct_clientlist; - register ZClientList_t *listp2; - - if (!listp) - return(ZSRV_BADASSOC); - for (listp2 = listp->q_forw; - listp2 != listp; - listp2 = listp2->q_forw) - /* walk down list, looking for him */ - if (listp2->zclt_client == client) { - xremque(listp2); - xfree(listp2); - if (listp->q_forw == listp) - return(EMPTY_CLASS); - else - return(ZERR_NONE); - } - return(ZSRV_BADASSOC); + Client **clientp; + + for (clientp = triplet->clients; *clientp; clientp++) { + if (*clientp == client || (realm && (*clientp)->realm == realm)) { + for (; *clientp; clientp++) + *clientp = clientp[1]; + return ZERR_NONE; + } + } + + return ZSRV_BADASSOC; } -static void free_class(class) - ZTriplet_t *class; +static void free_triplet(triplet) + Triplet *triplet; { - free_zstring(class->zct_dest.classname); - free_zstring(class->zct_dest.inst); - free_zstring(class->zct_dest.recip); - if (class->zct_acl != NULL) - xfree(class->zct_acl); - if (class->zct_clientlist != NULL) - xfree(class->zct_clientlist); - xfree(class); + if (triplet->clients) + free(triplet->clients); + free_string(triplet->dest.classname); + free_string(triplet->dest.inst); + free_string(triplet->dest.recip); + free(triplet); } - -void class_dump_subs(fp) - register FILE *fp; + +void triplet_dump_subs(fp) + FILE *fp; { int i; - ZTriplet_t *trpq, *trp; - ZClientList_t *cltq, *clt; + Triplet *triplet; + Client **clientp; for (i = 0; i < HASHSIZE; i++) { - trpq = class_bucket[i]; - if (!trpq) - continue; - for (trp = trpq->q_forw; trp != trpq; trp = trp->q_forw) { + for (triplet = triplet_bucket[i]; triplet; triplet = triplet->next) { fputs("Triplet '", fp); - subscr_quote(trp->zct_dest.classname->string, fp); + dump_quote(triplet->dest.classname->string, fp); fputs("' '", fp); - subscr_quote(trp->zct_dest.inst->string, fp); + dump_quote(triplet->dest.inst->string, fp); fputs("' '", fp); - subscr_quote(trp->zct_dest.recip->string, fp); + dump_quote(triplet->dest.recip->string, fp); fputs("':\n", fp); - cltq = trp->zct_clientlist; - if (!cltq) - continue; - for (clt = cltq->q_forw; clt != cltq; clt = clt->q_forw) { - fprintf(fp, "\t%s %d (%s)\n", - inet_ntoa(clt->zclt_client->zct_sin.sin_addr), - ntohs(clt->zclt_client->zct_sin.sin_port), - clt->zclt_client->zct_principal->string); + if (triplet->clients) { + for (clientp = triplet->clients; *clientp; clientp++) { + fprintf(fp, "\t%s %d (%s)\n", + inet_ntoa((*clientp)->addr.sin_addr), + ntohs((*clientp)->addr.sin_port), + (*clientp)->principal->string); + } } } } diff --git a/server/client.c b/server/client.c index 4646ac6..4e98f8f 100644 --- a/server/client.c +++ b/server/client.c @@ -12,10 +12,12 @@ */ #include <zephyr/mit-copyright.h> +#include "zserver.h" +#include <sys/socket.h> #if !defined (lint) && !defined (SABER) -static char rcsid_client_c[] = - "$Id$"; +static const char rcsid_client_c[] = +"$Id$"; #endif /* @@ -24,29 +26,26 @@ static char rcsid_client_c[] = * Code_t client_register(notice, who, client, server, wantdefaults) * ZNotice_t *notice; * struct sockaddr_in *who; - * ZClient_t **client; (RETURN) - * ZServerDesc_t *server; + * Client **client; (RETURN) + * Server *server; * int wantdefaults; * * Code_t client_deregister(client, host, flush) - * ZClient_t *client; - * ZHostList_t *host; + * Client *client; + * Host *host; * int flush; * - * ZClient_t *client_which_client(who, notice) + * Client *client_which_client(who, notice) * struct sockaddr_in *who; * ZNotice_t *notice; * * void client_dump_clients(fp, clist) * FILE *fp; - * ZClientList_t *clist; + * Client *clist; */ -#include "zserver.h" -#include <sys/socket.h> - /* - * register a client: allocate space, find or insert the address in the + * a client: allocate space, find or insert the address in the * server's list of hosts, initialize and insert the client into * the host's list of clients. * @@ -54,90 +53,61 @@ static char rcsid_client_c[] = * The caller should check by calling client_which_client */ +#define HASHSIZE 1024 +static Client *client_bucket[HASHSIZE]; + +#define INET_HASH(host, port) ((htonl((host)->s_addr) + \ + htons((unsigned short) (port))) % HASHSIZE) + +static Client *client_find __P((struct in_addr *host, unsigned int port)); + Code_t -client_register(notice, who, client, server, wantdefaults) - ZNotice_t *notice; - struct sockaddr_in *who; - register ZClient_t **client; - ZServerDesc_t *server; - int wantdefaults; +client_register(notice, host, client_p, wantdefaults) + ZNotice_t *notice; + struct in_addr *host; + Client **client_p; + int wantdefaults; { - register ZHostList_t *hlp = server->zs_hosts; - register ZHostList_t *hlp2; - register ZClientList_t *clist; - - /* chain the client's host onto this server's host list */ + Client *client; + Code_t retval; - if (!hlp) { /* bad host list */ - syslog(LOG_ERR, "cl_register: bad server host list"); - abort(); - } + /* chain the client's host onto this server's host list */ #if 1 - zdbug ((LOG_DEBUG, "client_register: adding %s at %s/%d", - notice->z_sender, inet_ntoa (who->sin_addr), - ntohs (notice->z_port))); + zdbug((LOG_DEBUG, "client_register: adding %s at %s/%d", + notice->z_sender, inet_ntoa(*host), ntohs(notice->z_port))); #endif - if (!notice->z_port) { - /* must be a non-zero port # */ - return(ZSRV_BADSUBPORT); - } - if (!(hlp2 = hostm_find_host(&who->sin_addr))) { - /* not here */ - return(ZSRV_HNOTFOUND); - } + if (!notice->z_port) + return ZSRV_BADSUBPORT; - /* hlp2 is now pointing to the client's host's address struct */ - - if (!hlp2->zh_clients) { - return(EINVAL); - } - - /* allocate a client struct */ - if (!(*client = (ZClient_t *) xmalloc(sizeof(ZClient_t)))) - return(ENOMEM); - - (*client)->last_msg = 0; - (*client)->last_check = 0; - (*client)->last_send = 0; - - if (!(clist = (ZClientList_t *) xmalloc(sizeof(ZClientList_t)))) { - xfree(*client); - return(ENOMEM); - } - - clist->q_forw = clist->q_back = clist; - clist->zclt_client = *client; - - /* initialize the struct */ - (void) memset((caddr_t) &(*client)->zct_sin, 0, - sizeof(struct sockaddr_in)); + *client_p = client = client_find(host, notice->z_port); + if (!client) { + *client_p = client = (Client *) malloc(sizeof(Client)); + if (!client) + return ENOMEM; + memset(&client->addr, 0, sizeof(struct sockaddr_in)); #ifdef KERBEROS - (void) memset((caddr_t) &(*client)->zct_cblock, 0, - sizeof((*client)->zct_cblock)); + memset(&client->session_key, 0, sizeof(client->session_key)); #endif - (*client)->zct_sin.sin_addr.s_addr = who->sin_addr.s_addr; - (*client)->zct_sin.sin_port = notice->z_port; - (*client)->zct_sin.sin_family = AF_INET; - (*client)->zct_subs = NULLZST; - (*client)->zct_principal = make_zstring(notice->z_sender,0); - - /* chain him in to the clients list in the host list*/ - - START_CRITICAL_CODE; - - xinsque(clist, hlp2->zh_clients); - - END_CRITICAL_CODE; - - if (!server->zs_dumping && wantdefaults) - /* add default subscriptions only if this is not - resulting from a brain dump, AND this request - wants defaults */ - return(subscr_def_subs(*client)); - else - return(ZERR_NONE); + client->last_msg = 0; + client->last_send = 0; + client->addr.sin_family = AF_INET; + client->addr.sin_addr.s_addr = host->s_addr; + client->addr.sin_port = notice->z_port; + client->subs = NULL; + client->realm = NULL; + client->principal = make_string(notice->z_sender, 0); + LIST_INSERT(&client_bucket[INET_HASH(&client->addr.sin_addr, + notice->z_port)], client); + } + + /* Add default subscriptions only if this is not resulting from a brain + * dump, AND this request wants defaults. */ + if (!bdumping && wantdefaults) + return subscr_def_subs(client); + else + return ZERR_NONE; } /* @@ -147,81 +117,73 @@ client_register(notice, who, client, server, wantdefaults) */ void -client_deregister(client, host, flush) - ZClient_t *client; - ZHostList_t *host; - int flush; +client_deregister(client, flush) + Client *client; + int flush; +{ + LIST_DELETE(client); + nack_release(client); + subscr_cancel_client(client); + free_string(client->principal); + if (flush) + uloc_flush_client(&client->addr); + free(client); +} + +void +client_flush_host(host) + struct in_addr *host; { - ZClientList_t *clients; - - START_CRITICAL_CODE; - - /* release any not-acked packets in the rexmit queue */ - nack_release(client); - - /* release subscriptions */ - (void) subscr_cancel_client(client); - - if (flush) - /* release locations if this is a punted client */ - (void) uloc_flush_client(&client->zct_sin); - - /* unthread and release this client */ - - if (host->zh_clients) - for (clients = host->zh_clients->q_forw; - clients != host->zh_clients; - clients = clients->q_forw) - if (clients->zclt_client == client) { - xremque(clients); - free_zstring(client->zct_principal); - xfree(client); - xfree(clients); - END_CRITICAL_CODE; - return; - } - syslog(LOG_CRIT, "clt_dereg: clt not in host list"); - abort(); - /*NOTREACHED*/ + int i; + Client *client, *next; + + for (i = 0; i < HASHSIZE; i++) { + for (client = client_bucket[i]; client; client = next) { + next = client->next; + if (client->addr.sin_addr.s_addr == host->s_addr) + client_deregister(client, 1); + } + } + uloc_hflush(host); } /* * find the client which sent the notice */ -ZClient_t * -client_which_client(who, notice) - struct sockaddr_in *who; - ZNotice_t *notice; +Client * +client_which_client(host, notice) + struct in_addr *host; + ZNotice_t *notice; { - register ZHostList_t *hlt; - register ZClientList_t *clients; + return client_find(host, notice->z_port); +} - if (!(hlt = hostm_find_host(&who->sin_addr))) { -#if 0 - zdbug((LOG_DEBUG,"cl_wh_clt: host not found")); -#endif - return(NULLZCNT); +Code_t +client_send_clients() +{ + int i; + Client *client; + Code_t retval; + + for (i = 0; i < HASHSIZE; i++) { + /* Allow packets to be processed between rows of the hash table. */ + if (packets_waiting()) { + bdumping = 0; + bdump_concurrent = 1; + handle_packet(); + bdump_concurrent = 0; + bdumping = 1; } - - if (!hlt->zh_clients) { -#if 1 - zdbug((LOG_DEBUG,"cl_wh_clt: no clients")); -#endif - return(NULLZCNT); + for (client = client_bucket[i]; client; client = client->next) { + if (client->subs) { + retval = subscr_send_subs(client); + if (retval != ZERR_NONE) + return retval; + } } - - for (clients = hlt->zh_clients->q_forw; - clients != hlt->zh_clients; - clients = clients->q_forw) - if (clients->zclt_client->zct_sin.sin_port == notice->z_port) { - return(clients->zclt_client); - } - -#if 1 - zdbug((LOG_DEBUG, "cl_wh_clt: no port")); -#endif - return(NULLZCNT); + } + return ZERR_NONE; } /* @@ -231,17 +193,35 @@ client_which_client(who, notice) */ void -client_dump_clients(fp, clist) - FILE *fp; - ZClientList_t *clist; +client_dump_clients(fp) + FILE *fp; { - register ZClientList_t *ptr; - - for (ptr = clist->q_forw; ptr != clist; ptr = ptr->q_forw) { - (void) fprintf(fp, "\t%d (%s):\n", - ntohs(ptr->zclt_client->zct_sin.sin_port), - ptr->zclt_client->zct_principal->string); - subscr_dump_subs(fp, ptr->zclt_client->zct_subs); + Client *client; + int i; + + for (i = 0; i < HASHSIZE; i++) { + for (client = client_bucket[i]; client; client = client->next) { + fprintf(fp, "\t%d (%s):\n", ntohs(client->addr.sin_port), + client->principal->string); + subscr_dump_subs(fp, client->subs); } - return; + } } + +static Client * +client_find(host, port) + struct in_addr *host; + unsigned int port; +{ + Client *client; + long hashval; + + hashval = INET_HASH(host, port); + for (client = client_bucket[hashval]; client; client = client->next) { + if (client->addr.sin_addr.s_addr == host->s_addr + && client->addr.sin_port == port) + return client; + } + return NULL; +} + diff --git a/server/common.c b/server/common.c index 87585b9..bff30a9 100644 --- a/server/common.c +++ b/server/common.c @@ -12,90 +12,78 @@ */ #include <zephyr/mit-copyright.h> +#include "zserver.h" #ifndef lint #ifndef SABER -static char rcsid_common_c[] = +static const char rcsid_common_c[] = "$Id$"; #endif /* SABER */ #endif /* lint */ -#include <zephyr/zephyr.h> -#include <stdio.h> -#include <ctype.h> -#include <syslog.h> -#include <string.h> -#include "unix.h" - /* common routines for the server */ -/* copy the string into newly allocated area */ +/* copy a string into a newly allocated area */ char * -#ifdef __STDC__ -strsave (Zconst char *sp) -#else strsave (sp) - Zconst char *sp; -#endif + const char *sp; { - register char *ret; + char *ret; - if((ret = (char *) xmalloc((unsigned) strlen(sp)+1)) == NULL) { - syslog(LOG_ERR, "no mem strdup'ing"); - abort(); + ret = (char *) malloc(strlen(sp) + 1); + if (!ret) { + syslog(LOG_CRIT, "no mem strdup'ing"); + abort(); } - (void) strcpy(ret,sp); - return(ret); + strcpy(ret, sp); + return ret; } /* The "& 0x5f" provides case-insensitivity for ASCII. */ unsigned long -#ifdef __STDC__ -hash (Zconst char *string) -#else -hash (string) - Zconst char *string; -#endif +hash(string) + const char *string; { - register unsigned long hval = 0; - register char cp; - - while (1) { - cp = *string++; - if (!cp) - break; - hval += cp & 0x5f; - - cp = *string++; - if (!cp) - break; - hval += (cp & 0x5f) * (3 + (1 << 16)); - - cp = *string++; - if (!cp) - break; - hval += (cp & 0x5f) * (1 + (1 << 8)); - - cp = *string++; - if (!cp) - break; - hval += (cp & 0x5f) * (1 + (1 << 12)); - - cp = *string++; - if (!cp) - break; - hval += (cp & 0x5f) * (1 + (1 << 4)); - - hval += ((long) hval) >> 18; - } - hval &= 0x7fffffff; - return hval; + unsigned long hval = 0; + char cp; + + while (1) { + cp = *string++; + if (!cp) + break; + hval += cp & 0x5f; + + cp = *string++; + if (!cp) + break; + hval += (cp & 0x5f) * (3 + (1 << 16)); + + cp = *string++; + if (!cp) + break; + hval += (cp & 0x5f) * (1 + (1 << 8)); + + cp = *string++; + if (!cp) + break; + hval += (cp & 0x5f) * (1 + (1 << 12)); + + cp = *string++; + if (!cp) + break; + hval += (cp & 0x5f) * (1 + (1 << 4)); + + hval += ((long) hval) >> 18; + } + + hval &= 0x7fffffff; + return hval; } /* Output a name, replacing newlines with \n and single quotes with \q. */ -void subscr_quote(p, fp) +void dump_quote(p, fp) char *p; FILE *fp; { diff --git a/server/dispatch.c b/server/dispatch.c index 2c2fb16..fed2336 100644 --- a/server/dispatch.c +++ b/server/dispatch.c @@ -12,21 +12,28 @@ */ #include <zephyr/mit-copyright.h> +#include "zserver.h" +#include <sys/socket.h> #ifndef lint #ifndef SABER -static char rcsid_dispatch_c[] = - "$Id$"; +static const char rcsid_dispatch_c[] = +"$Id$"; #endif #endif -#include "zserver.h" -#include <sys/socket.h> +#define NACKTAB_HASHSIZE 1023 +#define NACKTAB_HASHVAL(sockaddr, uid) (((sockaddr).sin_addr.s_addr ^ \ + (sockaddr).sin_port ^ \ + (uid).zuid_addr.s_addr ^ \ + (uid).tv.tv_sec ^ \ + (uid).tv.tv_usec) % NACKTAB_HASHSIZE) +#define HOSTS_SIZE_INIT 256 #ifdef DEBUG -Zconst char *ZNoticeKinds[9] = {"UNSAFE", "UNACKED", "ACKED", "HMACK", - "HMCTL", "SERVACK", "SERVNAK", "CLIENTACK", - "STAT"}; +ZCONST char *ZNoticeKinds[9] = {"UNSAFE", "UNACKED", "ACKED", "HMACK", + "HMCTL", "SERVACK", "SERVNAK", "CLIENTACK", + "STAT"}; #endif /* * @@ -40,10 +47,10 @@ Zconst char *ZNoticeKinds[9] = {"UNSAFE", "UNACKED", "ACKED", "HMACK", * void clt_ack(notice, who, sent) * ZNotice_t *notice; * struct sockaddr_in *who; - * ZSentType sent; + * Sent_type sent; * * void nack_release(client) - * ZClient_t *client; + * Client *client; * * void sendit(notice, auth, who) * ZNotice_t *notice; @@ -54,69 +61,59 @@ Zconst char *ZNoticeKinds[9] = {"UNSAFE", "UNACKED", "ACKED", "HMACK", * ZNotice_t *notice; * struct sockaddr_in *dest; * int auth; - * ZClient_t *client; + * Client *client; */ -/* patchable magic numbers controlling the retransmission rate and count */ -int num_rexmits = NUM_REXMITS; -long rexmit_secs = REXMIT_SECS; -long abs_timo = REXMIT_SECS*NUM_REXMITS + 10; +String *class_control, *class_admin, *class_hm, *class_ulogin, *class_ulocate; -ZSTRING *class_control, *class_admin, *class_hm, *class_ulogin, - *class_ulocate; +int rexmit_times[] = REXMIT_TIMES; -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -static void nack_cancel P((register ZNotice_t *, struct sockaddr_in *)); -static void dispatch P((ZNotice_t *, int, struct sockaddr_in *, int)); -static int send_to_dest P((ZNotice_t *, int, ZDestination *dest, int)); +static void nack_cancel __P((ZNotice_t *, struct sockaddr_in *)); +static void dispatch __P((ZNotice_t *, int, struct sockaddr_in *, int)); +static int send_to_dest __P((ZNotice_t *, int, Destination *dest, int, int)); +static void hostm_deathgram __P((struct sockaddr_in *, Server *)); +static char *hm_recipient __P((void)); -#undef P +Statistic realm_notices = {0, "inter-realm notices"}; +Statistic interserver_notices = {0, "inter-server notices"}; +Statistic hm_packets = {0, "hostmanager packets"}; +Statistic control_notices = {0, "client control notices"}; +Statistic message_notices = {0, "message notices"}; +Statistic login_notices = {0, "login notices"}; +Statistic i_s_ctls = {0, "inter-server control notices"}; +Statistic i_s_logins = {0, "inter-server login notices"}; +Statistic i_s_admins = {0, "inter-server admin notices"}; +Statistic i_s_locates = {0, "inter-server locate notices"}; +Statistic locate_notices = {0, "locate notices"}; +Statistic admin_notices = {0, "admin notices"}; -ZStatistic interserver_notices = {0, "inter-server notices"}; -ZStatistic hm_packets = {0, "hostmanager packets"}; -ZStatistic control_notices = {0, "client control notices"}; -ZStatistic message_notices = {0, "message notices"}; -ZStatistic login_notices = {0, "login notices"}; -ZStatistic i_s_ctls = {0, "inter-server control notices"}; -ZStatistic i_s_logins = {0, "inter-server login notices"}; -ZStatistic i_s_admins = {0, "inter-server admin notices"}; -ZStatistic i_s_locates = {0, "inter-server locate notices"}; -ZStatistic locate_notices = {0, "locate notices"}; -ZStatistic admin_notices = {0, "admin notices"}; +static Unacked *nacktab[NACKTAB_HASHSIZE]; +static struct in_addr *hosts; +static int hosts_size = 0, num_hosts = 0; static void -#ifdef __STDC__ -dump_stats (void *arg) -#else dump_stats (arg) -void *arg; -#endif + void *arg; { - syslog(LOG_INFO, "stats: %s: %d", hm_packets.str, hm_packets.val); - syslog(LOG_INFO, "stats: %s: %d", control_notices.str, - control_notices.val); - syslog(LOG_INFO, "stats: %s: %d", message_notices.str, - message_notices.val); - syslog(LOG_INFO, "stats: %s: %d", login_notices.str, - login_notices.val); - syslog(LOG_INFO, "stats: %s: %d", locate_notices.str, - locate_notices.val); - syslog(LOG_INFO, "stats: %s: %d", admin_notices.str, - admin_notices.val); - syslog(LOG_INFO, "stats: %s: %d", interserver_notices.str, - interserver_notices.val); - syslog(LOG_INFO, "stats: %s: %d", i_s_ctls.str, i_s_ctls.val); - syslog(LOG_INFO, "stats: %s: %d", i_s_logins.str, i_s_logins.val); - syslog(LOG_INFO, "stats: %s: %d", i_s_admins.str, i_s_admins.val); - syslog(LOG_INFO, "stats: %s: %d", i_s_locates.str, i_s_locates.val); - /* log stuff once an hour */ - (void) timer_set_rel ((long) 6*60*60, dump_stats, arg); + syslog(LOG_INFO, "stats: %s: %d", hm_packets.str, hm_packets.val); + syslog(LOG_INFO, "stats: %s: %d", control_notices.str, + control_notices.val); + syslog(LOG_INFO, "stats: %s: %d", message_notices.str, + message_notices.val); + syslog(LOG_INFO, "stats: %s: %d", login_notices.str, login_notices.val); + syslog(LOG_INFO, "stats: %s: %d", locate_notices.str, locate_notices.val); + syslog(LOG_INFO, "stats: %s: %d", admin_notices.str, admin_notices.val); + syslog(LOG_INFO, "stats: %s: %d", realm_notices.str, realm_notices.val); + syslog(LOG_INFO, "stats: %s: %d", interserver_notices.str, + interserver_notices.val); + syslog(LOG_INFO, "stats: %s: %d", i_s_ctls.str, i_s_ctls.val); + syslog(LOG_INFO, "stats: %s: %d", i_s_logins.str, i_s_logins.val); + syslog(LOG_INFO, "stats: %s: %d", i_s_admins.str, i_s_admins.val); + syslog(LOG_INFO, "stats: %s: %d", i_s_locates.str, i_s_locates.val); + + /* log stuff once an hour */ + timer_set_rel ((long) 6*60*60, dump_stats, arg); } /* @@ -127,123 +124,104 @@ void *arg; void handle_packet() { - Code_t status; - ZPacket_t input_packet; /* from the network */ - ZNotice_t new_notice; /* parsed from input_packet */ - int input_len; /* len of packet */ - struct sockaddr_in input_sin; /* Zconstructed for authent */ - struct sockaddr_in whoisit; /* for holding peer's address */ - int authentic; /* authentic flag */ - ZSrvPending_t *pending; /* pending packet */ - ZHostList_t *host; /* host ptr */ - int from_server; /* packet is from another server */ + Code_t status; + ZPacket_t input_packet; /* from the network */ + ZNotice_t new_notice; /* parsed from input_packet */ + int input_len; /* len of packet */ + struct sockaddr_in input_sin; /* Zconstructed for authent */ + struct sockaddr_in whoisit; /* for holding peer's address */ + int authentic; /* authentic flag */ + Pending *pending; /* pending packet */ + int from_server; /* packet is from another server */ + Realm *realm; /* foreign realm ptr */ #ifdef DEBUG - static int first_time = 1; + static int first_time = 1; #endif #ifdef DEBUG - /* Dump statistics five minutes after startup */ - if (first_time) { - first_time = 0; - (void) timer_set_rel (5*60, dump_stats, (void *) 0); - } -#endif - /* handle traffic */ - - if (otherservers[me_server_idx].zs_update_queue) { - /* something here for me; take care of it */ -#if 1 - zdbug((LOG_DEBUG, "internal queue process")); + /* Dump statistics five minutes after startup */ + if (first_time) { + first_time = 0; + timer_set_rel(5*60, dump_stats, NULL); + } #endif + /* handle traffic */ - pending = otherservers[me_server_idx].zs_update_queue->q_forw; - host = hostm_find_host(&(pending->pend_who.sin_addr)); - if (host && host->zh_locked) { - /* can't deal with it now. to preserve ordering, - we can't process other packets, esp. since we - may block since we don't really know if there - are things in the real queue. */ + if (otherservers[me_server_idx].queue) { + /* something here for me; take care of it */ #if 1 - zdbug((LOG_DEBUG,"host %s is locked", - inet_ntoa(host->zh_addr.sin_addr))); + zdbug((LOG_DEBUG, "internal queue process")); #endif - return; - } - pending = server_dequeue(me_server); /* we can do it, remove */ - - if ((status = ZParseNotice(pending->pend_packet, - pending->pend_len, - &new_notice)) != ZERR_NONE) { - syslog(LOG_ERR, - "bad notice parse (%s): %s", - inet_ntoa(pending->pend_who.sin_addr), - error_message(status)); - } else - dispatch(&new_notice, pending->pend_auth, - &pending->pend_who, 1); - server_pending_free(pending); - return; - } - /* - * nothing in internal queue, go to the external library - * queue/socket - */ - if ((status = ZReceivePacket(input_packet, - &input_len, - &whoisit)) != ZERR_NONE) { - syslog(LOG_ERR, - "bad packet receive: %s from %s", - error_message(status), inet_ntoa(whoisit.sin_addr)); - return; - } - npackets++; - if ((status = ZParseNotice(input_packet, - input_len, - &new_notice)) != ZERR_NONE) { - syslog(LOG_ERR, - "bad notice parse (%s): %s", - inet_ntoa(whoisit.sin_addr), - error_message(status)); - return; - } - if (server_which_server(&whoisit)) { - /* we need to parse twice--once to get - the source addr, second to check - authentication */ - (void) memset((caddr_t) &input_sin, 0, - sizeof(input_sin)); - input_sin.sin_addr.s_addr = new_notice.z_sender_addr.s_addr; - input_sin.sin_port = new_notice.z_port; - input_sin.sin_family = AF_INET; - authentic = ZCheckAuthentication(&new_notice, &input_sin); - from_server = 1; + + pending = server_dequeue(me_server); + + status = ZParseNotice(pending->packet, pending->len, &new_notice); + if (status != ZERR_NONE) { + syslog(LOG_ERR, "bad notice parse (%s): %s", + inet_ntoa(pending->who.sin_addr), error_message(status)); } else { - from_server = 0; - authentic = ZCheckAuthentication(&new_notice, &whoisit); + dispatch(&new_notice, pending->auth, &pending->who, 1); } - switch (authentic) { - case ZAUTH_YES: - authentic = 1; - break; - case ZAUTH_FAILED: - case ZAUTH_NO: - default: - authentic = 0; - break; + server_pending_free(pending); + return; + } + + /* + * nothing in internal queue, go to the external library + * queue/socket + */ + status = ZReceivePacket(input_packet, &input_len, &whoisit); + if (status != ZERR_NONE) { + syslog(LOG_ERR, "bad packet receive: %s from %s", + error_message(status), inet_ntoa(whoisit.sin_addr)); + return; + } + npackets++; + status = ZParseNotice(input_packet, input_len, &new_notice); + if (status != ZERR_NONE) { + syslog(LOG_ERR, "bad notice parse (%s): %s", + inet_ntoa(whoisit.sin_addr), error_message(status)); + return; + } + if (server_which_server(&whoisit)) { + /* we need to parse twice--once to get + the source addr, second to check + authentication */ + memset(&input_sin, 0, sizeof(input_sin)); + input_sin.sin_addr.s_addr = new_notice.z_sender_addr.s_addr; + input_sin.sin_port = new_notice.z_port; + input_sin.sin_family = AF_INET; + realm = realm_which_realm(&input_sin); + if (realm) { + authentic = ZCheckRealmAuthentication(&new_notice, &input_sin, + realm->name); + } else { + authentic = ZCheckAuthentication(&new_notice, &input_sin); } - if (whoisit.sin_port != hm_port && - strcasecmp (new_notice.z_class,ZEPHYR_ADMIN_CLASS) && - whoisit.sin_port != sock_sin.sin_port && - new_notice.z_kind != CLIENTACK) { - syslog(LOG_ERR, - "bad port %s/%d", - inet_ntoa(whoisit.sin_addr), - ntohs(whoisit.sin_port)); - return; + from_server = 1; + } else { + from_server = 0; + realm = realm_which_realm(&whoisit); + if (realm) { + authentic = ZCheckRealmAuthentication(&new_notice, &whoisit, + realm->name); + } else { + authentic = ZCheckAuthentication(&new_notice, &whoisit); } - message_notices.val++; - dispatch(&new_notice, authentic, &whoisit, from_server); + } + + if (whoisit.sin_port != hm_port && whoisit.sin_port != hm_srv_port && + strcasecmp(new_notice.z_class, ZEPHYR_ADMIN_CLASS) != 0 && + whoisit.sin_port != srv_addr.sin_port && + new_notice.z_kind != CLIENTACK) { + syslog(LOG_ERR, "bad port %s/%d", inet_ntoa(whoisit.sin_addr), + ntohs(whoisit.sin_port)); return; + } + + message_notices.val++; + dispatch(&new_notice, authentic, &whoisit, from_server); + return; } /* * Dispatch a notice. @@ -251,88 +229,110 @@ handle_packet() static void dispatch(notice, auth, who, from_server) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - int from_server; + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + int from_server; { - Code_t status; - ZSTRING *notice_class; - struct sockaddr_in who2; + Code_t status; + String *notice_class; + struct sockaddr_in who2; + int authflag; + Realm *realm; + char *cp; #ifdef DEBUG - char dbg_buf[BUFSIZ]; + char dbg_buf[BUFSIZ]; #endif - if ((int) notice->z_kind < (int) UNSAFE || - (int) notice->z_kind > (int) CLIENTACK) { - syslog(LOG_NOTICE, "bad notice kind 0x%x from %s", - (int) notice->z_kind, - inet_ntoa(who->sin_addr)); - return; - } + /* Set "authflag" to 1 or 0 for handler functions. Treat + * ZAUTH_CKSUM_FAILED as authentic except for sendit(), which is + * handled below. */ + switch (auth) { + case ZAUTH_YES: + case ZAUTH_CKSUM_FAILED: + authflag = 1; + break; + case ZAUTH_FAILED: + case ZAUTH_NO: + default: + authflag = 0; + break; + } + + if ((int) notice->z_kind < (int) UNSAFE || + (int) notice->z_kind > (int) CLIENTACK) { + syslog(LOG_NOTICE, "bad notice kind 0x%x from %s", notice->z_kind, + inet_ntoa(who->sin_addr)); + return; + } #if 0 - if (zdebug) { - (void) sprintf (dbg_buf, - "disp:%s '%s' '%s' '%s' notice to '%s' from '%s' %s/%d/%d", - ZNoticeKinds[(int) notice->z_kind], - notice->z_class, - notice->z_class_inst, - notice->z_opcode, - notice->z_recipient, - notice->z_sender, - inet_ntoa(who->sin_addr), - ntohs(who->sin_port), - ntohs(notice->z_port)); - syslog (LOG_DEBUG, "%s", dbg_buf); - } + if (zdebug) { + sprintf(dbg_buf, + "disp:%s '%s' '%s' '%s' notice to '%s' from '%s' %s/%d/%d", + ZNoticeKinds[(int) notice->z_kind], notice->z_class, + notice->z_class_inst, notice->z_opcode, notice->z_recipient, + notice->z_sender, inet_ntoa(who->sin_addr), + ntohs(who->sin_port), ntohs(notice->z_port)); + syslog(LOG_DEBUG, "%s", dbg_buf); + } #endif - if (notice->z_kind == CLIENTACK) { - nack_cancel(notice, who); - return; - } + if (notice->z_kind == CLIENTACK) { + nack_cancel(notice, who); + return; + } - who2 = *who; + who2 = *who; #if 0 - if (0 && from_server) { - /* incorporate server_dispatch here */ - } + if (0 && from_server) { + /* incorporate server_dispatch here */ + } #endif - notice_class = make_zstring(notice->z_class,1); - - if (from_server) { - interserver_notices.val++; - status = server_dispatch(notice, auth, who); - } else if (class_is_hm(notice_class)) { - hm_packets.val++; - status = hostm_dispatch(notice, auth, who, me_server); - } else if (class_is_control(notice_class)) { - control_notices.val++; - status = control_dispatch(notice, auth, who, me_server); - } else if (class_is_ulogin(notice_class)) { - login_notices.val++; - status = ulogin_dispatch(notice, auth, who, me_server); - } else if (class_is_ulocate(notice_class)) { - locate_notices.val++; - status = ulocate_dispatch(notice, auth, who, me_server); - } else if (class_is_admin(notice_class)) { - admin_notices.val++; - status = server_adispatch(notice, auth, who, me_server); + notice_class = make_string(notice->z_class,1); + + if (from_server) { + interserver_notices.val++; + status = server_dispatch(notice, authflag, who); + } else if (class_is_hm(notice_class)) { + hm_packets.val++; + status = hostm_dispatch(notice, authflag, who, me_server); + } else if (realm_which_realm(who) && !(class_is_admin(notice_class))) { + realm_notices.val++; + status = realm_dispatch(notice, authflag, who, me_server); + } else if (class_is_control(notice_class)) { + control_notices.val++; + status = control_dispatch(notice, authflag, who, me_server); + } else if (class_is_ulogin(notice_class)) { + login_notices.val++; + status = ulogin_dispatch(notice, authflag, who, me_server); + } else if (class_is_ulocate(notice_class)) { + locate_notices.val++; + status = ulocate_dispatch(notice, authflag, who, me_server); + } else if (class_is_admin(notice_class)) { + admin_notices.val++; + status = server_adispatch(notice, authflag, who, me_server); + } else { + if (auth == ZAUTH_CKSUM_FAILED) + authflag = 0; + if (!bound_for_local_realm(notice)) { + cp = strchr(notice->z_recipient, '@'); + if (!cp || + !(realm = realm_get_realm_by_name(realm_expand_realm(cp + 1)))) + sendit(notice, authflag, who, 0); + else + realm_handoff(notice, authflag, who, realm, 1); } else { - sendit (notice, auth, who); - free_zstring(notice_class); - return; + if (notice->z_recipient[0] == '@') + notice->z_recipient = ""; + sendit(notice, authflag, who, 1); } + free_string(notice_class); + return; + } - if (status == ZSRV_REQUEUE) { -#ifdef CONCURRENT - server_self_queue(notice, auth, who); -#else - syslog(LOG_ERR, "requeue while not concurr"); - abort(); -#endif - } - free_zstring(notice_class); + if (status == ZSRV_REQUEUE) + server_self_queue(notice, authflag, who); + free_string(notice_class); } /* @@ -340,101 +340,113 @@ dispatch(notice, auth, who, from_server) */ void -sendit(notice, auth, who) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; +sendit(notice, auth, who, external) + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + int external; { - static int send_counter = 0; - int any = 0; - ZAcl_t *acl; - ZDestination dest; - ZSTRING *class; - - class = make_zstring(notice->z_class,1); - if ((acl = class_get_acl(class)) != NULLZACLT) { - /* if controlled and not auth, fail */ - if (!auth) { - syslog(LOG_WARNING, "sendit unauthentic %s from %s", - notice->z_class, notice->z_sender); - clt_ack(notice, who, AUTH_FAILED); - free_zstring(class); - return; - } - /* if not auth to transmit, fail */ - if (!access_check(notice->z_sender, acl, TRANSMIT)) { - syslog(LOG_WARNING, "sendit unauthorized %s from %s", - notice->z_class, notice->z_sender); - clt_ack(notice, who, AUTH_FAILED); - free_zstring(class); - return; - } - /* sender != inst and not auth to send to others --> fail */ - if ((strcmp (notice->z_sender, notice->z_class_inst)) && - (!access_check(notice->z_sender, acl, INSTUID))) { - syslog(LOG_WARNING, - "sendit unauth uid %s %s.%s", - notice->z_sender, - notice->z_class, - notice->z_class_inst); + static int send_counter = 0; + char recipbuf[ANAME_SZ + INST_SZ + REALM_SZ + 3], *recipp; + int any = 0; + Acl *acl; + Destination dest; + String *class; + + class = make_string(notice->z_class, 1); + acl = class_get_acl(class); + if (acl != NULL) { + /* if controlled and not auth, fail */ + if (!auth) { + syslog(LOG_WARNING, "sendit unauthentic %s from %s", + notice->z_class, notice->z_sender); clt_ack(notice, who, AUTH_FAILED); - free_zstring(class); + free_string(class); return; - } } + /* if not auth to transmit, fail */ + if (!access_check(notice->z_sender, acl, TRANSMIT)) { + syslog(LOG_WARNING, "sendit unauthorized %s from %s", + notice->z_class, notice->z_sender); + clt_ack(notice, who, AUTH_FAILED); + free_string(class); + return; + } + /* sender != inst and not auth to send to others --> fail */ + if (strcmp(notice->z_sender, notice->z_class_inst) != 0 && + !access_check(notice->z_sender, acl, INSTUID)) { + syslog(LOG_WARNING, "sendit unauth uid %s %s.%s", notice->z_sender, + notice->z_class, notice->z_class_inst); + clt_ack(notice, who, AUTH_FAILED); + free_string(class); + return; + } + } + if (!realm_which_realm(who)) { if (memcmp(¬ice->z_sender_addr.s_addr, &who->sin_addr.s_addr, sizeof(notice->z_sender_addr.s_addr))) { /* someone is playing games... */ /* inet_ntoa returns pointer to static area */ /* max size is 255.255.255.255 */ char buffer[16]; - (void) strcpy(buffer, inet_ntoa(who->sin_addr)); + strcpy(buffer, inet_ntoa(who->sin_addr)); if (!auth) { - syslog(LOG_WARNING, "sendit unauthentic fake packet: claimed %s, real %s", + syslog(LOG_WARNING, + "sendit unauthentic fake packet: claimed %s, real %s", inet_ntoa(notice->z_sender_addr), buffer); clt_ack(notice, who, AUTH_FAILED); - free_zstring(class); + free_string(class); return; } if (ntohl(notice->z_sender_addr.s_addr) != 0) { - syslog(LOG_WARNING, "sendit invalid address: claimed %s, real %s", + syslog(LOG_WARNING, + "sendit invalid address: claimed %s, real %s", inet_ntoa(notice->z_sender_addr), buffer); clt_ack(notice, who, AUTH_FAILED); - free_zstring(class); + free_string(class); return; } syslog(LOG_WARNING, "sendit addr mismatch: claimed %s, real %s", inet_ntoa(notice->z_sender_addr), buffer); } - - /* Increment the send counter, used to prevent duplicate sends to - * clients. On the off-chance that we wrap around to 0, skip over - * it to prevent missing clients which have never had a packet - * sent to them. */ - send_counter++; - if (send_counter == 0) - send_counter = 1; - - /* Send to clients subscribed to the triplet itself. */ - dest.classname = class; - dest.inst = make_zstring(notice->z_class_inst, 1); - dest.recip = make_zstring(notice->z_recipient, 0); - if (send_to_dest(notice, auth, &dest, send_counter)) - any = 1; - - /* Send to clients subscribed to the triplet with the instance - * substituted with the wildcard instance. */ - free_zstring(dest.inst); - dest.inst = wildcard_instance; - if (send_to_dest(notice, auth, &dest, send_counter)) - any = 1; - - free_zstring(class); - free_zstring(dest.recip); - if (any) - ack(notice, who); - else - nack(notice, who); + } + + /* Increment the send counter, used to prevent duplicate sends to + * clients. On the off-chance that we wrap around to 0, skip over + * it to prevent missing clients which have never had a packet + * sent to them. */ + send_counter++; + if (send_counter == 0) + send_counter = 1; + + /* Send to clients subscribed to the triplet itself. */ + dest.classname = class; + dest.inst = make_string(notice->z_class_inst, 1); + if (bound_for_local_realm(notice) && *notice->z_recipient == '@') { + dest.recip = make_string("", 0); + } else { + strncpy(recipbuf, notice->z_recipient, sizeof(recipbuf)); + recipp = strrchr(&recipbuf, '@'); + if (recipp) + sprintf(recipp + 1, "%s", realm_expand_realm(recipp + 1)); + dest.recip = make_string(recipbuf, 0); + } + if (send_to_dest(notice, auth, &dest, send_counter, external)) + any = 1; + + /* Send to clients subscribed to the triplet with the instance + * substituted with the wildcard instance. */ + free_string(dest.inst); + dest.inst = wildcard_instance; + if (send_to_dest(notice, auth, &dest, send_counter, external)) + any = 1; + + free_string(class); + free_string(dest.recip); + if (any) + ack(notice, who); + else + nack(notice, who); } /* @@ -444,59 +456,59 @@ sendit(notice, auth, who) */ static int -send_to_dest(notice, auth, dest, send_counter) - ZNotice_t *notice; - int auth; - ZDestination *dest; - int send_counter; +send_to_dest(notice, auth, dest, send_counter, external) + ZNotice_t *notice; + int auth; + Destination *dest; + int send_counter; + int external; { - register ZClientList_t *list, *p; - register ZClient_t *client; - register int any = 0; - - list = triplet_lookup(dest); - if (list != NULLZCLT) { - for (p = list->q_forw; p != list; p = p->q_forw) { - client = p->zclt_client; - if (client->last_send == send_counter) - continue; - client->last_send = send_counter; - xmit(notice, &(client->zct_sin), auth, client); - any = 1; - } - } - return any; + Client **clientp; + int any = 0; + + clientp = triplet_lookup(dest); + if (!clientp) + return 0; + + for (; *clientp; clientp++) { + if ((*clientp)->last_send == send_counter) + continue; + (*clientp)->last_send = send_counter; + if ((*clientp)->realm && external) + realm_handoff(notice, auth, &clientp[0]->addr, clientp[0]->realm, + 1); + else + xmit(notice, &((*clientp)->addr), auth, *clientp); + any = 1; + } + + return any; } /* - * Clean up the not-yet-acked queue and release anything destined - * for the client. + * Release anything destined for the client in the not-yet-acked table. */ void nack_release(client) - ZClient_t *client; + Client *client; { - register ZNotAcked_t *nacked, *nack2; - - /* search the not-yet-acked list for anything destined to him, and - flush it. */ - for (nacked = nacklist->q_forw; - nacked != nacklist;) - if ((nacked->na_addr.sin_addr.s_addr == client->zct_sin.sin_addr.s_addr) && - (nacked->na_addr.sin_port == client->zct_sin.sin_port)) { - /* go back, since remque will change things */ - nack2 = nacked->q_back; - timer_reset(nacked->na_timer); - xremque(nacked); - xfree(nacked->na_packet); - xfree(nacked); - /* now that the remque adjusted the linked list, - we go forward again */ - nacked = nack2->q_forw; - } else - nacked = nacked->q_forw; - return; + int i; + Unacked *nacked, *next; + + for (i = 0; i < NACKTAB_HASHSIZE; i++) { + for (nacked = nacktab[i]; nacked; nacked = next) { + next = nacked->next; + if (nacked->dest.addr.sin_addr.s_addr == + client->addr.sin_addr.s_addr && + nacked->dest.addr.sin_port == client->addr.sin_port) { + timer_reset(nacked->timer); + LIST_DELETE(nacked); + free(nacked->packet); + free(nacked); + } + } + } } /* @@ -508,53 +520,50 @@ nack_release(client) /*ARGSUSED*/ Code_t xmit_frag(notice, buf, len, waitforack) - ZNotice_t *notice; - char *buf; - int len; - int waitforack; + ZNotice_t *notice; + char *buf; + int len; + int waitforack; { - char *savebuf; - register ZNotAcked_t *nacked; - Code_t retval; - - if ((retval = ZSendPacket(buf, len, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "xmit_frag send: %s", - error_message(retval)); - return(retval); - } - - /* now we've sent it, mark it as not ack'ed */ - - if (!(nacked = (ZNotAcked_t *)xmalloc(sizeof(ZNotAcked_t)))) { - /* no space: just punt */ - syslog(LOG_WARNING, "xmit_frag nack malloc"); - return(ENOMEM); - } - - if (!(savebuf = (char *)xmalloc(len))) { - /* no space: just punt */ - syslog(LOG_WARNING, "xmit_frag pack malloc"); - return(ENOMEM); - } - - (void) memcpy(savebuf, buf, len); - - nacked->na_rexmits = 0; - nacked->na_packet = savebuf; - nacked->na_srv_idx = 0; - nacked->na_addr = ZGetDestAddr(); - nacked->na_packsz = len; - nacked->na_uid = notice->z_uid; - nacked->q_forw = nacked->q_back = nacked; - nacked->na_abstimo = NOW + abs_timo; - - /* set a timer to retransmit when done */ - nacked->na_timer = timer_set_rel(rexmit_secs, - rexmit, - (void *) nacked); - /* chain in */ - xinsque(nacked, nacklist); - return(ZERR_NONE); + struct sockaddr_in sin; + char *savebuf; + Unacked *nacked; + Code_t retval; + int hashval; + + retval = ZSendPacket(buf, len, 0); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "xmit_frag send: %s", error_message(retval)); + return retval; + } + + /* now we've sent it, mark it as not ack'ed */ + nacked = (Unacked *) malloc(sizeof(Unacked)); + if (!nacked) { + /* no space: just punt */ + syslog(LOG_WARNING, "xmit_frag nack malloc"); + return ENOMEM; + } + + savebuf = (char *) malloc(len); + if (!savebuf) { + /* no space: just punt */ + syslog(LOG_WARNING, "xmit_frag pack malloc"); + free(nacked); + return ENOMEM; + } + + memcpy(savebuf, buf, len); + + sin = ZGetDestAddr(); + nacked->rexmits = 0; + nacked->packet = savebuf; + nacked->dest.addr = sin; + nacked->packsz = len; + nacked->uid = notice->z_uid; + nacked->timer = timer_set_rel(rexmit_times[0], rexmit, nacked); + LIST_INSERT(&nacktab[NACKTAB_HASHVAL(sin, nacked->uid)], nacked); + return(ZERR_NONE); } /* @@ -564,115 +573,97 @@ xmit_frag(notice, buf, len, waitforack) void xmit(notice, dest, auth, client) - ZNotice_t *notice; - struct sockaddr_in *dest; - int auth; - ZClient_t *client; + ZNotice_t *notice; + struct sockaddr_in *dest; + int auth; + Client *client; { - caddr_t noticepack; - register ZNotAcked_t *nacked; - int packlen; - Code_t retval; + char *noticepack; + Unacked *nacked; + int packlen; + Code_t retval; #if 0 - zdbug((LOG_DEBUG,"xmit")); + zdbug((LOG_DEBUG,"xmit")); #endif - if (!(noticepack = (caddr_t) xmalloc(sizeof(ZPacket_t)))) { - syslog(LOG_ERR, "xmit malloc"); - return; /* DON'T put on nack list */ + noticepack = (char *) malloc(sizeof(ZPacket_t)); + if (!noticepack) { + syslog(LOG_ERR, "xmit malloc"); + return; /* DON'T put on nack list */ + } + + packlen = sizeof(ZPacket_t); + + if (auth && client) { /* + we are distributing authentic and + we have a pointer to auth info + */ +#ifdef ZEPHYR_USES_KERBEROS + retval = ZFormatAuthenticNotice(notice, noticepack, packlen, &packlen, + client->session_key); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "xmit auth format: %s", error_message(retval)); + free(noticepack); + return; } - - packlen = sizeof(ZPacket_t); - - if (auth && client) { /* - we are distributing authentic and - we have a pointer to auth info - */ -#ifdef KERBEROS - - if ((retval = ZFormatAuthenticNotice(notice, - noticepack, - packlen, - &packlen, - client->zct_cblock)) - != ZERR_NONE) { - syslog(LOG_ERR, "xmit auth format: %s", - error_message(retval)); - xfree(noticepack); - return; - } -#else /* !KERBEROS */ - notice->z_auth = 1; - if ((retval = ZFormatSmallRawNotice(notice, - noticepack, - &packlen)) - != ZERR_NONE) { - syslog(LOG_ERR, "xmit auth/raw format: %s", - error_message(retval)); - xfree(noticepack); - return; - } -#endif /* KERBEROS */ - } else { - notice->z_auth = 0; - notice->z_authent_len = 0; - notice->z_ascii_authent = (char *)""; - if ((retval = ZFormatSmallRawNotice(notice, - noticepack, - &packlen)) != ZERR_NONE) { - syslog(LOG_ERR, "xmit format: %s", - error_message(retval)); - xfree(noticepack); - return; /* DON'T put on nack list */ - } +#else /* !ZEPHYR_USES_KERBEROS */ + notice->z_auth = 1; + retval = ZFormatSmallRawNotice(notice, noticepack, &packlen); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "xmit auth/raw format: %s", error_message(retval)); + free(noticepack); + return; + } +#endif /* ZEPHYR_USES_KERBEROS */ + } else { + notice->z_auth = 0; + notice->z_authent_len = 0; + notice->z_ascii_authent = (char *)""; + retval = ZFormatSmallRawNotice(notice, noticepack, &packlen); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "xmit format: %s", error_message(retval)); + free(noticepack); + return; /* DON'T put on nack list */ } + } #if 0 - zdbug((LOG_DEBUG," to %s/%d",inet_ntoa(dest->sin_addr), - ntohs(dest->sin_port))); + zdbug((LOG_DEBUG," to %s/%d", inet_ntoa(dest->sin_addr), + ntohs(dest->sin_port))); #endif - if ((retval = ZSetDestAddr(dest)) != ZERR_NONE) { - syslog(LOG_WARNING, "xmit set addr: %s", - error_message(retval)); - xfree(noticepack); - return; - } - if ((retval = ZSendPacket(noticepack, packlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "xmit xmit: (%s/%d) %s", - inet_ntoa(dest->sin_addr), ntohs(dest->sin_port), - error_message(retval)); - xfree(noticepack); - return; - } - - /* now we've sent it, mark it as not ack'ed */ - - if (!(nacked = (ZNotAcked_t *)xmalloc(sizeof(ZNotAcked_t)))) { - /* no space: just punt */ - syslog(LOG_WARNING, "xmit nack malloc"); - xfree(noticepack); - return; - } + retval = ZSetDestAddr(dest); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "xmit set addr: %s", error_message(retval)); + free(noticepack); + return; + } + retval = ZSendPacket(noticepack, packlen, 0); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "xmit xmit: (%s/%d) %s", inet_ntoa(dest->sin_addr), + ntohs(dest->sin_port), error_message(retval)); + free(noticepack); + return; + } - nacked->na_rexmits = 0; - nacked->na_packet = noticepack; - nacked->na_srv_idx = 0; /* XXX */ - nacked->na_addr = *dest; - nacked->na_packsz = packlen; - nacked->na_uid = notice->z_uid; - nacked->q_forw = nacked->q_back = nacked; - nacked->na_abstimo = NOW + abs_timo; - - /* set a timer to retransmit when done */ - nacked->na_timer = timer_set_rel(rexmit_secs, - rexmit, - (void *) nacked); - /* chain in */ - xinsque(nacked, nacklist); + /* now we've sent it, mark it as not ack'ed */ + nacked = (Unacked *) malloc(sizeof(Unacked)); + if (!nacked) { + /* no space: just punt */ + syslog(LOG_WARNING, "xmit nack malloc"); + free(noticepack); + return; + } + + nacked->rexmits = 0; + nacked->packet = noticepack; + nacked->dest.addr = *dest; + nacked->packsz = packlen; + nacked->uid = notice->z_uid; + nacked->timer = timer_set_rel(rexmit_times[0], rexmit, nacked); + LIST_INSERT(&nacktab[NACKTAB_HASHVAL(*dest, nacked->uid)], nacked); } - /* * Retransmit the packet specified. If we have timed out or retransmitted * too many times, punt the packet and initiate the host recovery algorithm @@ -680,67 +671,59 @@ xmit(notice, dest, auth, client) */ void -#ifdef __STDC__ -rexmit(void *arg) -#else rexmit(arg) - void *arg; -#endif + void *arg; { - register ZNotAcked_t *nackpacket = (ZNotAcked_t*) arg; - int retval; - ZNotice_t dummy_notice; - register ZClient_t *client; + Unacked *nacked = (Unacked *) arg; + int retval; + ZNotice_t dummy_notice; + Client *client; #if 1 - zdbug((LOG_DEBUG,"rexmit")); + syslog(LOG_DEBUG, "rexmit %s/%d #%d time %d", + inet_ntoa(nacked->dest.addr.sin_addr), + ntohs(nacked->dest.addr.sin_port), nacked->rexmits + 1, NOW); #endif - if (++(nackpacket->na_rexmits) > num_rexmits || - NOW > nackpacket->na_abstimo) { - /* possibly dead client */ - - dummy_notice.z_port = nackpacket->na_addr.sin_port; - - client = client_which_client(&nackpacket->na_addr, - &dummy_notice); - - /* unlink & free packet */ - xremque(nackpacket); - xfree(nackpacket->na_packet); - xfree(nackpacket); - - /* initiate recovery */ - if (client) - server_recover(client); - return; + nacked->rexmits++; + if (rexmit_times[nacked->rexmits] == -1) { + /* Unresponsive client, find it in our database. */ + dummy_notice.z_port = nacked->dest.addr.sin_port; + client = client_which_client(&nacked->dest.addr.sin_addr, + &dummy_notice); + + /* unlink & free nacked */ + LIST_DELETE(nacked); + free(nacked->packet); + free(nacked); + + /* Kill the client. */ + if (client) { + server_kill_clt(client); + client_deregister(client, 1); } - /* retransmit the packet */ - -#if 0 - zdbug((LOG_DEBUG," to %s/%d", - inet_ntoa(nackpacket->na_addr.sin_addr), - ntohs(nackpacket->na_addr.sin_port))); -#endif - if ((retval = ZSetDestAddr(&nackpacket->na_addr)) - != ZERR_NONE) { - syslog(LOG_WARNING, "rexmit set addr: %s", - error_message(retval)); - goto requeue; - - } - if ((retval = ZSendPacket(nackpacket->na_packet, - nackpacket->na_packsz, 0)) != ZERR_NONE) - syslog(LOG_WARNING, "rexmit xmit: %s", error_message(retval)); - -requeue: - /* reset the timer */ - nackpacket->na_timer = timer_set_rel(rexmit_secs, - rexmit, - (void *) nackpacket); return; + } + /* retransmit the packet */ +#if 0 + zdbug((LOG_DEBUG," to %s/%d", inet_ntoa(nacked->dest.addr.sin_addr), + ntohs(nacked->dest.addr.sin_port))); +#endif + retval = ZSetDestAddr(&nacked->dest.addr); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "rexmit set addr: %s", error_message(retval)); + } else { + retval = ZSendPacket(nacked->packet, nacked->packsz, 0); + if (retval != ZERR_NONE) + syslog(LOG_WARNING, "rexmit xmit: %s", error_message(retval)); + } + + /* reset the timer */ + nacked->timer = timer_set_rel(rexmit_times[nacked->rexmits], rexmit, + nacked); + return; } /* @@ -752,93 +735,81 @@ requeue: void clt_ack(notice, who, sent) - ZNotice_t *notice; - struct sockaddr_in *who; - ZSentType sent; + ZNotice_t *notice; + struct sockaddr_in *who; + Sent_type sent; { - ZNotice_t acknotice; - ZPacket_t ackpack; - int packlen; - int notme = 0; - char *sent_name; - Code_t retval; - - if (bdumping) { /* don't ack while dumping */ + ZNotice_t acknotice; + ZPacket_t ackpack; + int packlen; + int notme = 0; + char *sent_name; + Code_t retval; + + if (bdumping) { /* don't ack while dumping */ #if 1 - zdbug((LOG_DEBUG,"bdumping, no ack")); -#endif - return; - } - - acknotice = *notice; - - acknotice.z_kind = SERVACK; - switch (sent) { - case SENT: - acknotice.z_message = ZSRVACK_SENT; - sent_name = "sent"; - break; - case NOT_FOUND: - acknotice.z_message = ZSRVACK_FAIL; - acknotice.z_kind = SERVNAK; - sent_name = "fail"; - break; - case AUTH_FAILED: - acknotice.z_kind = SERVNAK; - acknotice.z_message = ZSRVACK_NOTSENT; - sent_name = "nak/not_sent"; - break; - case NOT_SENT: - acknotice.z_message = ZSRVACK_NOTSENT; - sent_name = "not_sent"; - break; - default: - abort (); - } - -#if 0 - zdbug((LOG_DEBUG,"clt_ack type %s for %d to %s/%d", - sent_name, - ntohs(notice->z_port), - inet_ntoa(who->sin_addr), - ntohs(who->sin_port))); + zdbug((LOG_DEBUG,"bdumping, no ack")); #endif + return; + } + + acknotice = *notice; + + acknotice.z_kind = SERVACK; + switch (sent) { + case SENT: + acknotice.z_message = ZSRVACK_SENT; + sent_name = "sent"; + break; + case NOT_FOUND: + acknotice.z_message = ZSRVACK_FAIL; + acknotice.z_kind = SERVNAK; + sent_name = "fail"; + break; + case AUTH_FAILED: + acknotice.z_kind = SERVNAK; + acknotice.z_message = ZSRVACK_NOTSENT; + sent_name = "nak/not_sent"; + break; + case NOT_SENT: + acknotice.z_message = ZSRVACK_NOTSENT; + sent_name = "not_sent"; + break; + default: + abort (); + } - if (!server_which_server(who) && - (hostm_find_server(&who->sin_addr) != me_server)) { #if 0 - zdbug((LOG_DEBUG,"not me")); + zdbug((LOG_DEBUG,"clt_ack type %s for %d to %s/%d", sent_name, + ntohs(notice->z_port), inet_ntoa(who->sin_addr), + ntohs(who->sin_port))); #endif - notme = 1; - } - acknotice.z_multinotice = ""; + acknotice.z_multinotice = ""; - /* leave room for the trailing null */ - acknotice.z_message_len = strlen(acknotice.z_message) + 1; + /* leave room for the trailing null */ + acknotice.z_message_len = strlen(acknotice.z_message) + 1; - packlen = sizeof(ackpack); + packlen = sizeof(ackpack); - if ((retval = ZFormatSmallRawNotice(&acknotice, - ackpack, - &packlen)) != ZERR_NONE) { - syslog(LOG_ERR, "clt_ack format: %s",error_message(retval)); - return; - } - if ((retval = ZSetDestAddr(who)) != ZERR_NONE) { - syslog(LOG_WARNING, "clt_ack set addr: %s", - error_message(retval)); - return; - } - if ((retval = ZSendPacket(ackpack, packlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "clt_ack xmit: %s", error_message(retval)); - return; - } - else - zdbug ((LOG_DEBUG, "packet sent")); - if (notme) - hostm_deathgram(who, me_server); + retval = ZFormatSmallRawNotice(&acknotice, ackpack, &packlen); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "clt_ack format: %s", error_message(retval)); return; + } + retval = ZSetDestAddr(who); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "clt_ack set addr: %s", error_message(retval)); + return; + } + retval = ZSendPacket(ackpack, packlen, 0); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "clt_ack xmit: %s", error_message(retval)); + return; + } else { + zdbug((LOG_DEBUG, "packet sent")); + } + return; } /* @@ -848,36 +819,36 @@ clt_ack(notice, who, sent) static void nack_cancel(notice, who) - register ZNotice_t *notice; - struct sockaddr_in *who; + ZNotice_t *notice; + struct sockaddr_in *who; { - register ZNotAcked_t *nacked; + Unacked *nacked; + int hashval; - /* search the not-yet-acked list for this packet, and - flush it. */ + /* search the not-yet-acked table for this packet, and flush it. */ #if 0 - zdbug((LOG_DEBUG, "nack_cancel: %s:%08X,%08X", - inet_ntoa (notice->z_uid.zuid_addr), - notice->z_uid.tv.tv_sec, notice->z_uid.tv.tv_usec)); + zdbug((LOG_DEBUG, "nack_cancel: %s:%08X,%08X", + inet_ntoa(notice->z_uid.zuid_addr), + notice->z_uid.tv.tv_sec, notice->z_uid.tv.tv_usec)); #endif - for (nacked = nacklist->q_forw; - nacked != nacklist; - nacked = nacked->q_forw) - if ((nacked->na_addr.sin_addr.s_addr == who->sin_addr.s_addr) && - (nacked->na_addr.sin_port == who->sin_port)) - if (ZCompareUID(&nacked->na_uid, ¬ice->z_uid)) { - timer_reset(nacked->na_timer); - xfree(nacked->na_packet); - xremque(nacked); - xfree(nacked); - return; - } + hashval = NACKTAB_HASHVAL(*who, notice->z_uid); + for (nacked = nacktab[hashval]; nacked; nacked = nacked->next) { + if (nacked->dest.addr.sin_addr.s_addr == who->sin_addr.s_addr + && nacked->dest.addr.sin_port == who->sin_port + && ZCompareUID(&nacked->uid, ¬ice->z_uid)) { + timer_reset(nacked->timer); + free(nacked->packet); + LIST_DELETE(nacked); + free(nacked); + return; + } + } + #if 1 - zdbug((LOG_DEBUG,"nack_cancel: nack not found %s:%08X,%08X", - inet_ntoa (notice->z_uid.zuid_addr), - notice->z_uid.tv.tv_sec, notice->z_uid.tv.tv_usec)); + zdbug((LOG_DEBUG,"nack_cancel: nack not found %s:%08X,%08X", + inet_ntoa (notice->z_uid.zuid_addr), + notice->z_uid.tv.tv_sec, notice->z_uid.tv.tv_usec)); #endif - return; } /* for compatibility when sending subscription information to old clients */ @@ -885,184 +856,329 @@ nack_cancel(notice, who) #define OLD_ZEPHYR_VERSION "ZEPH0.0" #endif /* OLD_COMPAT */ +/* Dispatch an HM_CTL notice. */ + +Code_t +hostm_dispatch(notice, auth, who, server) + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + Server *server; +{ + Server *owner; + char *opcode = notice->z_opcode; + Code_t retval; + int i, add = 0, remove = 0; + +#if 0 + zdbug((LOG_DEBUG,"hm_disp")); +#endif + + if (notice->z_kind == HMACK) { + /* Ignore. */ + ; + } else if (notice->z_kind != HMCTL) { +#if 0 + zdbug((LOG_DEBUG, "bogus HM packet")); +#endif + clt_ack(notice, who, AUTH_FAILED); + } else if (strcmp(opcode, HM_FLUSH) == 0) { + client_flush_host(&who->sin_addr); + if (server == me_server) + server_forward(notice, auth, who); + } else if (strcmp(opcode, HM_BOOT) == 0) { + client_flush_host(&who->sin_addr); + if (server == me_server) { + server_forward(notice, auth, who); + ack(notice, who); + add = 1; + } + } else if (strcmp(opcode, HM_ATTACH) == 0) { + if (server == me_server) { + server_forward(notice, auth, who); + ack(notice, who); + add = 1; + } else { + remove = 1; + } + } else if (strcmp(opcode, HM_DETACH) == 0) { + remove = 1; + } else { + syslog(LOG_WARNING, "hm_dispatch: unknown opcode %s", opcode); + } + + if (add) { + for (i = 0; i < num_hosts; i++) { + if (hosts[i].s_addr == who->sin_addr.s_addr) + break; + } + if (i == num_hosts) { + if (hosts_size == 0) { + hosts = (struct in_addr *) malloc(HOSTS_SIZE_INIT * + sizeof(struct in_addr)); + if (!hosts) + return ENOMEM; + hosts_size = HOSTS_SIZE_INIT; + } else if (num_hosts == hosts_size) { + hosts = (struct in_addr *) realloc(hosts, hosts_size * 2 * + sizeof(struct in_addr)); + if (!hosts) + return ENOMEM; + hosts_size *= 2; + } + hosts[num_hosts++] = who->sin_addr; + } + } else if (remove) { + for (i = 0; i < num_hosts; i++) { + if (hosts[i].s_addr == who->sin_addr.s_addr) { + memmove(&hosts[i], &hosts[i + 1], num_hosts - (i + 1)); + num_hosts--; + break; + } + } + } + return ZERR_NONE; +} + /* * Dispatch a ZEPHYR_CTL notice. */ Code_t control_dispatch(notice, auth, who, server) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - ZServerDesc_t *server; + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + Server *server; { - register char *opcode = notice->z_opcode; - ZClient_t *client; - ZHostList_t *host; - Code_t retval; - int wantdefs; - - /* - * ZEPHYR_CTL Opcodes expected are: - * BOOT (inst HM): host has booted; flush data. - * CLIENT_SUBSCRIBE: process with the subscription mananger. - * CLIENT_UNSUBSCRIBE: "" - * CLIENT_CANCELSUB: "" - */ - - zdbug ((LOG_DEBUG, "ctl_disp: opc=%s", opcode)); - - if (!strcasecmp (notice->z_class_inst, ZEPHYR_CTL_HM)) - return(hostm_dispatch(notice, auth, who, server)); - else if (!strcmp (opcode, CLIENT_GIMMESUBS) || - !strcmp (opcode, CLIENT_GIMMEDEFS)) { - /* this special case is before the auth check so that - someone who has no subscriptions does NOT get a SERVNAK - but rather an empty list. Note we must therefore - check authentication inside subscr_sendlist */ + char *opcode = notice->z_opcode; + Client *client; + Code_t retval; + int wantdefs; + Realm *realm; + struct sockaddr_in newwho; + + /* + * ZEPHYR_CTL Opcodes expected are: + * BOOT (inst HM): host has booted; flush data. + * CLIENT_SUBSCRIBE: process with the subscription mananger. + * CLIENT_UNSUBSCRIBE: "" + * CLIENT_CANCELSUB: "" + */ + + zdbug((LOG_DEBUG, "ctl_disp: opc=%s", opcode)); + + newwho.sin_addr.s_addr = notice->z_sender_addr.s_addr; + newwho.sin_port = notice->z_port; + realm = realm_which_realm(&newwho); + if (realm) + return(realm_control_dispatch(notice, auth, who, server, realm)); + + if (strcasecmp(notice->z_class_inst, ZEPHYR_CTL_HM) == 0) { + return hostm_dispatch(notice, auth, who, server); + } else if (strcmp(opcode, CLIENT_GIMMESUBS) == 0 || + strcmp(opcode, CLIENT_GIMMEDEFS) == 0) { + /* this special case is before the auth check so that + someone who has no subscriptions does NOT get a SERVNAK + but rather an empty list. Note we must therefore + check authentication inside subscr_sendlist */ #ifdef OLD_COMPAT - /* only acknowledge if *not* old version; the old version - acknowledges the packet with the reply */ - if (strcmp (notice->z_version, OLD_ZEPHYR_VERSION)) - ack(notice, who); + /* only acknowledge if *not* old version; the old version + acknowledges the packet with the reply */ + if (strcmp(notice->z_version, OLD_ZEPHYR_VERSION) != 0) + ack(notice, who); #else /* !OLD_COMPAT */ - ack(notice, who); + ack(notice, who); #endif /* OLD_COMPAT */ - subscr_sendlist(notice, auth, who); - return(ZERR_NONE); - } else if (!auth) { + subscr_sendlist(notice, auth, who); + return ZERR_NONE; + } else if (!auth) { #if 0 - zdbug((LOG_DEBUG,"unauth ctrl_disp")); + zdbug((LOG_DEBUG,"unauth ctrl_disp")); #endif - if (server == me_server) - clt_ack(notice, who, AUTH_FAILED); - return(ZERR_NONE); + if (server == me_server) + clt_ack(notice, who, AUTH_FAILED); + return ZERR_NONE; + } + + wantdefs = strcmp(opcode, CLIENT_SUBSCRIBE_NODEFS); + if (!wantdefs || strcmp(opcode, CLIENT_SUBSCRIBE) == 0) { + /* subscription notice */ + retval = client_register(notice, &who->sin_addr, &client, wantdefs); + if (retval != ZERR_NONE) { + syslog(LOG_NOTICE, "subscr %s/%s/%d failed: %s", + notice->z_sender, inet_ntoa(who->sin_addr), + ntohs(notice->z_port), error_message(retval)); + if (server == me_server) { + if (retval == ZSRV_BADSUBPORT) + clt_ack(notice, who, AUTH_FAILED); + else + nack(notice, who); + } + return(ZERR_NONE); } - - /* the rest of the expected opcodes modify state; check for - unlocked host first */ - host = hostm_find_host(&who->sin_addr); - if (host && host->zh_locked) - return(ZSRV_REQUEUE); - - wantdefs = strcmp (opcode, CLIENT_SUBSCRIBE_NODEFS); - if (!wantdefs || !strcmp (opcode, CLIENT_SUBSCRIBE)) { - /* subscription notice */ - if (!(client = client_which_client(who, notice))) { - if ((retval = client_register(notice, - who, - &client, - server, - wantdefs)) != ZERR_NONE) - { - syslog(LOG_NOTICE, - "subscr. register %s/%s/%d failed: %s", - notice->z_sender, - inet_ntoa(who->sin_addr), - ntohs(notice->z_port), - error_message(retval)); - if (server == me_server) { - if (retval == ZSRV_BADSUBPORT) { - clt_ack(notice, who, AUTH_FAILED); - } else - hostm_deathgram(who, me_server); - } - return(ZERR_NONE); - } - if (!(client = client_which_client(who, notice))) { - syslog(LOG_CRIT, "subscr reg. failure"); - abort(); - } - } - if (strcmp (client->zct_principal->string, notice->z_sender)) { - /* you may only subscribe for your own clients */ - if (server == me_server) - clt_ack(notice, who, AUTH_FAILED); - return(ZERR_NONE); - } -#ifdef KERBEROS - /* in case it's changed */ - (void) memcpy((caddr_t) client->zct_cblock, (caddr_t) ZGetSession(), - sizeof(C_Block)); + if (strcmp(client->principal->string, notice->z_sender) != 0) { + /* you may only subscribe for your own clients */ + if (server == me_server) + clt_ack(notice, who, AUTH_FAILED); + return ZERR_NONE; + } +#ifdef ZEPHYR_USES_KERBEROS + /* in case it's changed */ + memcpy(client->session_key, ZGetSession(), sizeof(C_Block)); #endif - if ((retval = subscr_subscribe(client,notice)) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr failed: %s", - error_message(retval)); - if (server == me_server) - nack(notice, who); - return(ZERR_NONE); - } - } else if (!strcmp(opcode, CLIENT_UNSUBSCRIBE)) { - if ((client = client_which_client(who,notice)) != NULLZCNT) { - if (strcmp(client->zct_principal->string, notice->z_sender)) { - /* you may only cancel for your own clients */ - if (server == me_server) - clt_ack(notice, who, AUTH_FAILED); - return(ZERR_NONE); - } + retval = subscr_subscribe(client, notice); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "subscr failed: %s", error_message(retval)); + if (server == me_server) + nack(notice, who); + return ZERR_NONE; + } + } else if (strcmp(opcode, CLIENT_UNSUBSCRIBE) == 0) { + client = client_which_client(&who->sin_addr, notice); + if (client != NULL) { + if (strcmp(client->principal->string, notice->z_sender) != 0) { + /* you may only cancel for your own clients */ + if (server == me_server) + clt_ack(notice, who, AUTH_FAILED); + return ZERR_NONE; + } #if 0 - if (zdebug) { - if (server == me_server) - syslog (LOG_DEBUG, - "subscription cancel for %s/%d\n", - inet_ntoa (who->sin_addr), - ntohs (who->sin_port)); - else - syslog (LOG_DEBUG, - "subscription cancel for %s/%d from %s\n", - inet_ntoa (who->sin_addr), - ntohs (who->sin_port), - server->addr); - } -#endif - (void) subscr_cancel(who, notice); + if (zdebug) { + if (server == me_server) { + syslog(LOG_DEBUG, "subscription cancel for %s/%d\n", + inet_ntoa(who->sin_addr), ntohs(who->sin_port)); } else { - nack(notice, who); - return(ZERR_NONE); + syslog(LOG_DEBUG, + "subscription cancel for %s/%d from %s\n", + inet_ntoa(who->sin_addr), ntohs(who->sin_port), + server->addr_str); } - } else if (!strcmp(opcode, CLIENT_CANCELSUB)) { - /* canceling subscriptions implies I can punt info about - this client */ - if ((client = client_which_client(who,notice)) != NULLZCNT) { - if (strcmp(client->zct_principal->string, notice->z_sender)) { - /* you may only cancel for your own clients */ - if (server == me_server) - clt_ack(notice, who, AUTH_FAILED); - return(ZERR_NONE); - } - if (host) { - /* don't flush locations here, let him - do it explicitly */ + } +#endif + subscr_cancel(who, notice); + } else { + nack(notice, who); + return ZERR_NONE; + } + } else if (strcmp(opcode, CLIENT_CANCELSUB) == 0) { + /* canceling subscriptions implies I can punt info about this client */ + client = client_which_client(&who->sin_addr, notice); + if (client == NULL) { #if 0 - zdbug((LOG_DEBUG, "cancelsub clt_dereg %s/%d", - inet_ntoa (who->sin_addr), - ntohs (who->sin_port))); + zdbug((LOG_DEBUG,"can_sub not found client")); #endif - hostm_lose_ignore(client); - (void) client_deregister(client, host, 0); - } - - } - if (!client || !host) { + if (server == me_server) + nack(notice, who); + return ZERR_NONE; + } + if (strcmp(client->principal->string, notice->z_sender) != 0) { + /* you may only cancel for your own clients */ + if (server == me_server) + clt_ack(notice, who, AUTH_FAILED); + return ZERR_NONE; + } + /* don't flush locations here, let him do it explicitly */ #if 0 - zdbug((LOG_DEBUG,"can_sub not found client")); + zdbug((LOG_DEBUG, "cancelsub clt_dereg %s/%d", + inet_ntoa(who->sin_addr), ntohs(who->sin_port))); #endif - if (server == me_server) - nack(notice, who); - return(ZERR_NONE); - } + client_deregister(client, 0); + } else { + syslog(LOG_WARNING, "unknown ctl opcode %s", opcode); + if (server == me_server) + nack(notice, who); + return ZERR_NONE; + } + + if (server == me_server) { + ack(notice, who); + server_forward(notice, auth, who); + } + return ZERR_NONE; +} + +void +hostm_shutdown() +{ + int i, s, newserver; + struct sockaddr_in sin; + + for (i = 0; i < nservers; i++) { + if (i != me_server_idx && otherservers[i].state == SERV_UP) + break; + } + newserver = (i < nservers); + for (i = 0; i < num_hosts; i++) { + sin.sin_addr = hosts[i]; + sin.sin_port = hm_port; + if (newserver) { + while (1) { + s = (random() % (nservers - 1)) + 1; + if (otherservers[s].state == SERV_UP) + break; + } + hostm_deathgram(&sin, &otherservers[s]); } else { - syslog(LOG_WARNING, "unknown ctl opcode %s", opcode); - if (server == me_server) - nack(notice, who); - return(ZERR_NONE); + hostm_deathgram(&sin, NULL); } + } +} - if (server == me_server) { - ack(notice, who); - server_forward(notice, auth, who); - } - return(ZERR_NONE); +static void +hostm_deathgram(sin, server) + struct sockaddr_in *sin; + Server *server; +{ + Code_t retval; + int shutlen; + ZNotice_t shutnotice; + char *shutpack; + + shutnotice.z_kind = HMCTL; + shutnotice.z_port = sin->sin_port; /* we are sending it */ + shutnotice.z_class = HM_CTL_CLASS; + shutnotice.z_class_inst = HM_CTL_SERVER; + shutnotice.z_opcode = SERVER_SHUTDOWN; + shutnotice.z_sender = HM_CTL_SERVER; + shutnotice.z_recipient = hm_recipient(); + shutnotice.z_default_format = ""; + shutnotice.z_num_other_fields = 0; + shutnotice.z_message = (server) ? server->addr_str : NULL; + shutnotice.z_message_len = (server) ? strlen(server->addr_str) + 1 : 0; + + retval = ZFormatNotice(&shutnotice, &shutpack, &shutlen, ZNOAUTH); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "hm_shut format: %s",error_message(retval)); + return; + } + retval = ZSetDestAddr(sin); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "hm_shut set addr: %s", error_message(retval)); + free(shutpack); + return; + } + retval = ZSendPacket(shutpack, shutlen, 0); + if (retval != ZERR_NONE) + syslog(LOG_WARNING, "hm_shut xmit: %s", error_message(retval)); + free(shutpack); +} + +static char * +hm_recipient() +{ + static char *recipient; + char *realm; + + if (recipient) + return recipient; + + realm = ZGetRealm(); + if (!realm) + realm = "???"; + recipient = (char *) malloc(strlen(realm) + 4); + strcpy (recipient, "hm@"); + strcat (recipient, realm); + return recipient; } - diff --git a/server/dispatch.c.auth b/server/dispatch.c.auth deleted file mode 100644 index 8707c2f..0000000 --- a/server/dispatch.c.auth +++ /dev/null @@ -1,1078 +0,0 @@ -/* This file is part of the Project Athena Zephyr Notification System. - * It contains functions for dispatching a notice. - * - * Created by: John T. Kohl - * - * $Source$ - * $Author$ - * - * Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology. - * For copying and distribution information, see the file - * "mit-copyright.h". - */ - -#include <zephyr/mit-copyright.h> - -#ifndef lint -#ifndef SABER -static char rcsid_dispatch_c[] = - "$Id$"; -#endif -#endif - -#include "zserver.h" -#include <sys/socket.h> - -#ifdef DEBUG -Zconst char *ZNoticeKinds[9] = {"UNSAFE", "UNACKED", "ACKED", "HMACK", - "HMCTL", "SERVACK", "SERVNAK", "CLIENTACK", - "STAT"}; -#endif -/* - * - * External Routines: - * - * void dispatch(notice, auth, who) - * ZNotice_t *notice; - * int auth; - * struct sockaddr_in *who; - * - * void clt_ack(notice, who, sent) - * ZNotice_t *notice; - * struct sockaddr_in *who; - * ZSentType sent; - * - * void nack_release(client) - * ZClient_t *client; - * - * void sendit(notice, auth, who) - * ZNotice_t *notice; - * int auth; - * struct sockaddr_in *who; - * - * void xmit(notice, dest, auth, client) - * ZNotice_t *notice; - * struct sockaddr_in *dest; - * int auth; - * ZClient_t *client; - */ - - -/* patchable magic numbers controlling the retransmission rate and count */ -int num_rexmits = NUM_REXMITS; -long rexmit_secs = REXMIT_SECS; -long abs_timo = REXMIT_SECS*NUM_REXMITS + 10; - -ZSTRING *class_control, *class_admin, *class_hm, *class_ulogin, - *class_ulocate; - -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -static void nack_cancel P((register ZNotice_t *, struct sockaddr_in *)); -static void dispatch P((ZNotice_t *, int, struct sockaddr_in *, int)); -static int send_to_dest P((ZNotice_t *, int, ZDestination *dest, int)); - -#undef P - -ZStatistic interserver_notices = {0, "inter-server notices"}; -ZStatistic hm_packets = {0, "hostmanager packets"}; -ZStatistic control_notices = {0, "client control notices"}; -ZStatistic message_notices = {0, "message notices"}; -ZStatistic login_notices = {0, "login notices"}; -ZStatistic i_s_ctls = {0, "inter-server control notices"}; -ZStatistic i_s_logins = {0, "inter-server login notices"}; -ZStatistic i_s_admins = {0, "inter-server admin notices"}; -ZStatistic i_s_locates = {0, "inter-server locate notices"}; -ZStatistic locate_notices = {0, "locate notices"}; -ZStatistic admin_notices = {0, "admin notices"}; - -static void -#ifdef __STDC__ -dump_stats (void *arg) -#else -dump_stats (arg) -void *arg; -#endif -{ - syslog(LOG_INFO, "stats: %s: %d", hm_packets.str, hm_packets.val); - syslog(LOG_INFO, "stats: %s: %d", control_notices.str, - control_notices.val); - syslog(LOG_INFO, "stats: %s: %d", message_notices.str, - message_notices.val); - syslog(LOG_INFO, "stats: %s: %d", login_notices.str, - login_notices.val); - syslog(LOG_INFO, "stats: %s: %d", locate_notices.str, - locate_notices.val); - syslog(LOG_INFO, "stats: %s: %d", admin_notices.str, - admin_notices.val); - syslog(LOG_INFO, "stats: %s: %d", interserver_notices.str, - interserver_notices.val); - syslog(LOG_INFO, "stats: %s: %d", i_s_ctls.str, i_s_ctls.val); - syslog(LOG_INFO, "stats: %s: %d", i_s_logins.str, i_s_logins.val); - syslog(LOG_INFO, "stats: %s: %d", i_s_admins.str, i_s_admins.val); - syslog(LOG_INFO, "stats: %s: %d", i_s_locates.str, i_s_locates.val); - /* log stuff once an hour */ - (void) timer_set_rel ((long) 6*60*60, dump_stats, arg); -} - -/* - * Handle an input packet. - * Warning: this function may be called from within a brain dump. - */ - -void -handle_packet() -{ - Code_t status; - ZPacket_t input_packet; /* from the network */ - ZNotice_t new_notice; /* parsed from input_packet */ - int input_len; /* len of packet */ - struct sockaddr_in input_sin; /* Zconstructed for authent */ - struct sockaddr_in whoisit; /* for holding peer's address */ - int authentic; /* authentic flag */ - ZSrvPending_t *pending; /* pending packet */ - ZHostList_t *host; /* host ptr */ - int from_server; /* packet is from another server */ -#ifdef DEBUG - static int first_time = 1; -#endif - -#ifdef DEBUG - /* Dump statistics five minutes after startup */ - if (first_time) { - first_time = 0; - (void) timer_set_rel (5*60, dump_stats, (void *) 0); - } -#endif - /* handle traffic */ - - if (otherservers[me_server_idx].zs_update_queue) { - /* something here for me; take care of it */ -#if 1 - zdbug((LOG_DEBUG, "internal queue process")); -#endif - - pending = otherservers[me_server_idx].zs_update_queue->q_forw; - host = hostm_find_host(&(pending->pend_who.sin_addr)); - if (host && host->zh_locked) { - /* can't deal with it now. to preserve ordering, - we can't process other packets, esp. since we - may block since we don't really know if there - are things in the real queue. */ -#if 1 - zdbug((LOG_DEBUG,"host %s is locked", - inet_ntoa(host->zh_addr.sin_addr))); -#endif - return; - } - pending = server_dequeue(me_server); /* we can do it, remove */ - - if ((status = ZParseNotice(pending->pend_packet, - pending->pend_len, - &new_notice)) != ZERR_NONE) { - syslog(LOG_ERR, - "bad notice parse (%s): %s", - inet_ntoa(pending->pend_who.sin_addr), - error_message(status)); - } else - dispatch(&new_notice, pending->pend_auth, - &pending->pend_who, 1); - server_pending_free(pending); - return; - } - /* - * nothing in internal queue, go to the external library - * queue/socket - */ - if ((status = ZReceivePacket(input_packet, - &input_len, - &whoisit)) != ZERR_NONE) { - syslog(LOG_ERR, - "bad packet receive: %s from %s", - error_message(status), inet_ntoa(whoisit.sin_addr)); - return; - } - npackets++; - if ((status = ZParseNotice(input_packet, - input_len, - &new_notice)) != ZERR_NONE) { - syslog(LOG_ERR, - "bad notice parse (%s): %s", - inet_ntoa(whoisit.sin_addr), - error_message(status)); - return; - } - if (server_which_server(&whoisit)) { - /* we need to parse twice--once to get - the source addr, second to check - authentication */ - (void) memset((caddr_t) &input_sin, 0, - sizeof(input_sin)); - input_sin.sin_addr.s_addr = new_notice.z_sender_addr.s_addr; - input_sin.sin_port = new_notice.z_port; - input_sin.sin_family = AF_INET; - authentic = ZCheckAuthentication(&new_notice, &input_sin); - from_server = 1; - } else { - from_server = 0; - authentic = ZCheckAuthentication(&new_notice, &whoisit); - } - - if (whoisit.sin_port != hm_port && - strcasecmp (new_notice.z_class,ZEPHYR_ADMIN_CLASS) && - whoisit.sin_port != sock_sin.sin_port && - new_notice.z_kind != CLIENTACK) { - syslog(LOG_ERR, - "bad port %s/%d", - inet_ntoa(whoisit.sin_addr), - ntohs(whoisit.sin_port)); - return; - } - - message_notices.val++; - dispatch(&new_notice, authentic, &whoisit, from_server); - return; -} -/* - * Dispatch a notice. - */ - -static void -dispatch(notice, auth, who, from_server) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - int from_server; -{ - Code_t status; - ZSTRING *notice_class; - struct sockaddr_in who2; - int authflag; -#ifdef DEBUG - char dbg_buf[BUFSIZ]; -#endif - - /* Set "authflag" to 1 or 0 for handler functions. Treat - * ZAUTH_CKSUM_FAILED as authentic except for sendit(), which is - * handled below. */ - switch (auth) { - case ZAUTH_YES: - case ZAUTH_CKSUM_FAILED: - authflag = 1; - break; - case ZAUTH_FAILED: - case ZAUTH_NO: - default: - authflag = 0; - break; - } - - if ((int) notice->z_kind < (int) UNSAFE || - (int) notice->z_kind > (int) CLIENTACK) { - syslog(LOG_NOTICE, "bad notice kind 0x%x from %s", - (int) notice->z_kind, - inet_ntoa(who->sin_addr)); - return; - } -#if 0 - if (zdebug) { - (void) sprintf (dbg_buf, - "disp:%s '%s' '%s' '%s' notice to '%s' from '%s' %s/%d/%d", - ZNoticeKinds[(int) notice->z_kind], - notice->z_class, - notice->z_class_inst, - notice->z_opcode, - notice->z_recipient, - notice->z_sender, - inet_ntoa(who->sin_addr), - ntohs(who->sin_port), - ntohs(notice->z_port)); - syslog (LOG_DEBUG, "%s", dbg_buf); - } -#endif - - if (notice->z_kind == CLIENTACK) { - nack_cancel(notice, who); - return; - } - - who2 = *who; -#if 0 - if (0 && from_server) { - /* incorporate server_dispatch here */ - } -#endif - notice_class = make_zstring(notice->z_class,1); - - if (from_server) { - interserver_notices.val++; - status = server_dispatch(notice, auth, who); - } else if (class_is_hm(notice_class)) { - hm_packets.val++; - status = hostm_dispatch(notice, auth, who, me_server); - } else if (class_is_control(notice_class)) { - control_notices.val++; - status = control_dispatch(notice, auth, who, me_server); - } else if (class_is_ulogin(notice_class)) { - login_notices.val++; - status = ulogin_dispatch(notice, auth, who, me_server); - } else if (class_is_ulocate(notice_class)) { - locate_notices.val++; - status = ulocate_dispatch(notice, auth, who, me_server); - } else if (class_is_admin(notice_class)) { - admin_notices.val++; - status = server_adispatch(notice, auth, who, me_server); - } else { - if (auth == ZAUTH_CKSUM_FAILED) - authflag = 0; - sendit (notice, auth, who); - free_zstring(notice_class); - return; - } - - if (status == ZSRV_REQUEUE) { -#ifdef CONCURRENT - server_self_queue(notice, auth, who); -#else - syslog(LOG_ERR, "requeue while not concurr"); - abort(); -#endif - } - free_zstring(notice_class); -} - -/* - * Send a notice off to those clients who have subscribed to it. - */ - -void -sendit(notice, auth, who) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; -{ - static int send_counter = 0; - int any = 0; - ZAcl_t *acl; - ZDestination dest; - ZSTRING *class; - - class = make_zstring(notice->z_class,1); - if ((acl = class_get_acl(class)) != NULLZACLT) { - /* if controlled and not auth, fail */ - if (!auth) { - syslog(LOG_WARNING, "sendit unauthentic %s from %s", - notice->z_class, notice->z_sender); - clt_ack(notice, who, AUTH_FAILED); - free_zstring(class); - return; - } - /* if not auth to transmit, fail */ - if (!access_check(notice->z_sender, acl, TRANSMIT)) { - syslog(LOG_WARNING, "sendit unauthorized %s from %s", - notice->z_class, notice->z_sender); - clt_ack(notice, who, AUTH_FAILED); - free_zstring(class); - return; - } - /* sender != inst and not auth to send to others --> fail */ - if ((strcmp (notice->z_sender, notice->z_class_inst)) && - (!access_check(notice->z_sender, acl, INSTUID))) { - syslog(LOG_WARNING, - "sendit unauth uid %s %s.%s", - notice->z_sender, - notice->z_class, - notice->z_class_inst); - clt_ack(notice, who, AUTH_FAILED); - free_zstring(class); - return; - } - } - if (memcmp(¬ice->z_sender_addr.s_addr, &who->sin_addr.s_addr, - sizeof(notice->z_sender_addr.s_addr))) { - /* someone is playing games... */ - /* inet_ntoa returns pointer to static area */ - /* max size is 255.255.255.255 */ - char buffer[16]; - (void) strcpy(buffer, inet_ntoa(who->sin_addr)); - if (!auth) { - syslog(LOG_WARNING, "sendit unauthentic fake packet: claimed %s, real %s", - inet_ntoa(notice->z_sender_addr), buffer); - clt_ack(notice, who, AUTH_FAILED); - free_zstring(class); - return; - } - if (ntohl(notice->z_sender_addr.s_addr) != 0) { - syslog(LOG_WARNING, "sendit invalid address: claimed %s, real %s", - inet_ntoa(notice->z_sender_addr), buffer); - clt_ack(notice, who, AUTH_FAILED); - free_zstring(class); - return; - } - syslog(LOG_WARNING, "sendit addr mismatch: claimed %s, real %s", - inet_ntoa(notice->z_sender_addr), buffer); - } - - /* Increment the send counter, used to prevent duplicate sends to - * clients. On the off-chance that we wrap around to 0, skip over - * it to prevent missing clients which have never had a packet - * sent to them. */ - send_counter++; - if (send_counter == 0) - send_counter = 1; - - /* Send to clients subscribed to the triplet itself. */ - dest.classname = class; - dest.inst = make_zstring(notice->z_class_inst, 1); - dest.recip = make_zstring(notice->z_recipient, 0); - if (send_to_dest(notice, auth, &dest, send_counter)) - any = 1; - - /* Send to clients subscribed to the triplet with the instance - * substituted with the wildcard instance. */ - free_zstring(dest.inst); - dest.inst = wildcard_instance; - if (send_to_dest(notice, auth, &dest, send_counter)) - any = 1; - - free_zstring(class); - free_zstring(dest.recip); - if (any) - ack(notice, who); - else - nack(notice, who); -} - -/* - * Send to each client in the list. Avoid duplicates by setting - * last_send on each client to send_counter, a nonce which is updated - * by sendit() above. - */ - -static int -send_to_dest(notice, auth, dest, send_counter) - ZNotice_t *notice; - int auth; - ZDestination *dest; - int send_counter; -{ - register ZClientList_t *list, *p; - register ZClient_t *client; - register int any = 0; - - list = triplet_lookup(dest); - if (list != NULLZCLT) { - for (p = list->q_forw; p != list; p = p->q_forw) { - client = p->zclt_client; - if (client->last_send == send_counter) - continue; - client->last_send = send_counter; - xmit(notice, &(client->zct_sin), auth, client); - any = 1; - } - } - return any; -} - -/* - * Clean up the not-yet-acked queue and release anything destined - * for the client. - */ - -void -nack_release(client) - ZClient_t *client; -{ - register ZNotAcked_t *nacked, *nack2; - - /* search the not-yet-acked list for anything destined to him, and - flush it. */ - for (nacked = nacklist->q_forw; - nacked != nacklist;) - if ((nacked->na_addr.sin_addr.s_addr == client->zct_sin.sin_addr.s_addr) && - (nacked->na_addr.sin_port == client->zct_sin.sin_port)) { - /* go back, since remque will change things */ - nack2 = nacked->q_back; - timer_reset(nacked->na_timer); - xremque(nacked); - xfree(nacked->na_packet); - xfree(nacked); - /* now that the remque adjusted the linked list, - we go forward again */ - nacked = nack2->q_forw; - } else - nacked = nacked->q_forw; - return; -} - -/* - * Send one packet of a fragmented message to a client. After transmitting, - * put it onto the not ack'ed list. - */ - -/* the arguments must be the same as the arguments to Z_XmitFragment */ -/*ARGSUSED*/ -Code_t -xmit_frag(notice, buf, len, waitforack) - ZNotice_t *notice; - char *buf; - int len; - int waitforack; -{ - char *savebuf; - register ZNotAcked_t *nacked; - Code_t retval; - - if ((retval = ZSendPacket(buf, len, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "xmit_frag send: %s", - error_message(retval)); - return(retval); - } - - /* now we've sent it, mark it as not ack'ed */ - - if (!(nacked = (ZNotAcked_t *)xmalloc(sizeof(ZNotAcked_t)))) { - /* no space: just punt */ - syslog(LOG_WARNING, "xmit_frag nack malloc"); - return(ENOMEM); - } - - if (!(savebuf = (char *)xmalloc(len))) { - /* no space: just punt */ - syslog(LOG_WARNING, "xmit_frag pack malloc"); - return(ENOMEM); - } - - (void) memcpy(savebuf, buf, len); - - nacked->na_rexmits = 0; - nacked->na_packet = savebuf; - nacked->na_srv_idx = 0; - nacked->na_addr = ZGetDestAddr(); - nacked->na_packsz = len; - nacked->na_uid = notice->z_uid; - nacked->q_forw = nacked->q_back = nacked; - nacked->na_abstimo = NOW + abs_timo; - - /* set a timer to retransmit when done */ - nacked->na_timer = timer_set_rel(rexmit_secs, - rexmit, - (void *) nacked); - /* chain in */ - xinsque(nacked, nacklist); - return(ZERR_NONE); -} - -/* - * Send the notice to the client. After transmitting, put it onto the - * not ack'ed list. - */ - -void -xmit(notice, dest, auth, client) - ZNotice_t *notice; - struct sockaddr_in *dest; - int auth; - ZClient_t *client; -{ - caddr_t noticepack; - register ZNotAcked_t *nacked; - int packlen; - Code_t retval; - -#if 0 - zdbug((LOG_DEBUG,"xmit")); -#endif - - if (!(noticepack = (caddr_t) xmalloc(sizeof(ZPacket_t)))) { - syslog(LOG_ERR, "xmit malloc"); - return; /* DON'T put on nack list */ - } - - packlen = sizeof(ZPacket_t); - - if (auth && client) { /* - we are distributing authentic and - we have a pointer to auth info - */ -#ifdef KERBEROS - - if ((retval = ZFormatAuthenticNotice(notice, - noticepack, - packlen, - &packlen, - client->zct_cblock)) - != ZERR_NONE) { - syslog(LOG_ERR, "xmit auth format: %s", - error_message(retval)); - xfree(noticepack); - return; - } -#else /* !KERBEROS */ - notice->z_auth = 1; - if ((retval = ZFormatSmallRawNotice(notice, - noticepack, - &packlen)) - != ZERR_NONE) { - syslog(LOG_ERR, "xmit auth/raw format: %s", - error_message(retval)); - xfree(noticepack); - return; - } -#endif /* KERBEROS */ - } else { - notice->z_auth = 0; - notice->z_authent_len = 0; - notice->z_ascii_authent = (char *)""; - if ((retval = ZFormatSmallRawNotice(notice, - noticepack, - &packlen)) != ZERR_NONE) { - syslog(LOG_ERR, "xmit format: %s", - error_message(retval)); - xfree(noticepack); - return; /* DON'T put on nack list */ - } - } -#if 0 - zdbug((LOG_DEBUG," to %s/%d",inet_ntoa(dest->sin_addr), - ntohs(dest->sin_port))); -#endif - if ((retval = ZSetDestAddr(dest)) != ZERR_NONE) { - syslog(LOG_WARNING, "xmit set addr: %s", - error_message(retval)); - xfree(noticepack); - return; - } - if ((retval = ZSendPacket(noticepack, packlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "xmit xmit: (%s/%d) %s", - inet_ntoa(dest->sin_addr), ntohs(dest->sin_port), - error_message(retval)); - xfree(noticepack); - return; - } - - /* now we've sent it, mark it as not ack'ed */ - - if (!(nacked = (ZNotAcked_t *)xmalloc(sizeof(ZNotAcked_t)))) { - /* no space: just punt */ - syslog(LOG_WARNING, "xmit nack malloc"); - xfree(noticepack); - return; - } - - nacked->na_rexmits = 0; - nacked->na_packet = noticepack; - nacked->na_srv_idx = 0; /* XXX */ - nacked->na_addr = *dest; - nacked->na_packsz = packlen; - nacked->na_uid = notice->z_uid; - nacked->q_forw = nacked->q_back = nacked; - nacked->na_abstimo = NOW + abs_timo; - - /* set a timer to retransmit when done */ - nacked->na_timer = timer_set_rel(rexmit_secs, - rexmit, - (void *) nacked); - /* chain in */ - xinsque(nacked, nacklist); - -} - - -/* - * Retransmit the packet specified. If we have timed out or retransmitted - * too many times, punt the packet and initiate the host recovery algorithm - * Else, increment the count and re-send the notice packet. - */ - -void -#ifdef __STDC__ -rexmit(void *arg) -#else -rexmit(arg) - void *arg; -#endif -{ - register ZNotAcked_t *nackpacket = (ZNotAcked_t*) arg; - int retval; - ZNotice_t dummy_notice; - register ZClient_t *client; - -#if 1 - zdbug((LOG_DEBUG,"rexmit")); -#endif - - if (++(nackpacket->na_rexmits) > num_rexmits || - NOW > nackpacket->na_abstimo) { - /* possibly dead client */ - - dummy_notice.z_port = nackpacket->na_addr.sin_port; - - client = client_which_client(&nackpacket->na_addr, - &dummy_notice); - - /* unlink & free packet */ - xremque(nackpacket); - xfree(nackpacket->na_packet); - xfree(nackpacket); - - /* initiate recovery */ - if (client) - server_recover(client); - return; - } - - /* retransmit the packet */ - -#if 0 - zdbug((LOG_DEBUG," to %s/%d", - inet_ntoa(nackpacket->na_addr.sin_addr), - ntohs(nackpacket->na_addr.sin_port))); -#endif - if ((retval = ZSetDestAddr(&nackpacket->na_addr)) - != ZERR_NONE) { - syslog(LOG_WARNING, "rexmit set addr: %s", - error_message(retval)); - goto requeue; - - } - if ((retval = ZSendPacket(nackpacket->na_packet, - nackpacket->na_packsz, 0)) != ZERR_NONE) - syslog(LOG_WARNING, "rexmit xmit: %s", error_message(retval)); - -requeue: - /* reset the timer */ - nackpacket->na_timer = timer_set_rel(rexmit_secs, - rexmit, - (void *) nackpacket); - return; - -} - -/* - * Send an acknowledgement to the sending client, by sending back the - * header from the original notice with the z_kind field changed to either - * SERVACK or SERVNAK, and the contents of the message either SENT or - * NOT_SENT, depending on the value of the sent argument. - */ - -void -clt_ack(notice, who, sent) - ZNotice_t *notice; - struct sockaddr_in *who; - ZSentType sent; -{ - ZNotice_t acknotice; - ZPacket_t ackpack; - int packlen; - int notme = 0; - char *sent_name; - Code_t retval; - - if (bdumping) { /* don't ack while dumping */ -#if 1 - zdbug((LOG_DEBUG,"bdumping, no ack")); -#endif - return; - } - - acknotice = *notice; - - acknotice.z_kind = SERVACK; - switch (sent) { - case SENT: - acknotice.z_message = ZSRVACK_SENT; - sent_name = "sent"; - break; - case NOT_FOUND: - acknotice.z_message = ZSRVACK_FAIL; - acknotice.z_kind = SERVNAK; - sent_name = "fail"; - break; - case AUTH_FAILED: - acknotice.z_kind = SERVNAK; - acknotice.z_message = ZSRVACK_NOTSENT; - sent_name = "nak/not_sent"; - break; - case NOT_SENT: - acknotice.z_message = ZSRVACK_NOTSENT; - sent_name = "not_sent"; - break; - default: - abort (); - } - -#if 0 - zdbug((LOG_DEBUG,"clt_ack type %s for %d to %s/%d", - sent_name, - ntohs(notice->z_port), - inet_ntoa(who->sin_addr), - ntohs(who->sin_port))); -#endif - - if (!server_which_server(who) && - (hostm_find_server(&who->sin_addr) != me_server)) { -#if 0 - zdbug((LOG_DEBUG,"not me")); -#endif - notme = 1; - } - - acknotice.z_multinotice = ""; - - /* leave room for the trailing null */ - acknotice.z_message_len = strlen(acknotice.z_message) + 1; - - packlen = sizeof(ackpack); - - if ((retval = ZFormatSmallRawNotice(&acknotice, - ackpack, - &packlen)) != ZERR_NONE) { - syslog(LOG_ERR, "clt_ack format: %s",error_message(retval)); - return; - } - if ((retval = ZSetDestAddr(who)) != ZERR_NONE) { - syslog(LOG_WARNING, "clt_ack set addr: %s", - error_message(retval)); - return; - } - if ((retval = ZSendPacket(ackpack, packlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "clt_ack xmit: %s", error_message(retval)); - return; - } - else - zdbug ((LOG_DEBUG, "packet sent")); - if (notme) - hostm_deathgram(who, me_server); - return; -} - -/* - * An ack has arrived. - * remove the packet matching this notice from the not-yet-acked queue - */ - -static void -nack_cancel(notice, who) - register ZNotice_t *notice; - struct sockaddr_in *who; -{ - register ZNotAcked_t *nacked; - - /* search the not-yet-acked list for this packet, and - flush it. */ -#if 0 - zdbug((LOG_DEBUG, "nack_cancel: %s:%08X,%08X", - inet_ntoa (notice->z_uid.zuid_addr), - notice->z_uid.tv.tv_sec, notice->z_uid.tv.tv_usec)); -#endif - for (nacked = nacklist->q_forw; - nacked != nacklist; - nacked = nacked->q_forw) - if ((nacked->na_addr.sin_addr.s_addr == who->sin_addr.s_addr) && - (nacked->na_addr.sin_port == who->sin_port)) - if (ZCompareUID(&nacked->na_uid, ¬ice->z_uid)) { - timer_reset(nacked->na_timer); - xfree(nacked->na_packet); - xremque(nacked); - xfree(nacked); - return; - } -#if 1 - zdbug((LOG_DEBUG,"nack_cancel: nack not found %s:%08X,%08X", - inet_ntoa (notice->z_uid.zuid_addr), - notice->z_uid.tv.tv_sec, notice->z_uid.tv.tv_usec)); -#endif - return; -} - -/* for compatibility when sending subscription information to old clients */ -#ifdef OLD_COMPAT -#define OLD_ZEPHYR_VERSION "ZEPH0.0" -#endif /* OLD_COMPAT */ - -/* - * Dispatch a ZEPHYR_CTL notice. - */ - -Code_t -control_dispatch(notice, auth, who, server) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - ZServerDesc_t *server; -{ - register char *opcode = notice->z_opcode; - ZClient_t *client; - ZHostList_t *host; - Code_t retval; - int wantdefs; - - /* - * ZEPHYR_CTL Opcodes expected are: - * BOOT (inst HM): host has booted; flush data. - * CLIENT_SUBSCRIBE: process with the subscription mananger. - * CLIENT_UNSUBSCRIBE: "" - * CLIENT_CANCELSUB: "" - */ - - zdbug ((LOG_DEBUG, "ctl_disp: opc=%s", opcode)); - - if (!strcasecmp (notice->z_class_inst, ZEPHYR_CTL_HM)) - return(hostm_dispatch(notice, auth, who, server)); - else if (!strcmp (opcode, CLIENT_GIMMESUBS) || - !strcmp (opcode, CLIENT_GIMMEDEFS)) { - /* this special case is before the auth check so that - someone who has no subscriptions does NOT get a SERVNAK - but rather an empty list. Note we must therefore - check authentication inside subscr_sendlist */ -#ifdef OLD_COMPAT - /* only acknowledge if *not* old version; the old version - acknowledges the packet with the reply */ - if (strcmp (notice->z_version, OLD_ZEPHYR_VERSION)) - ack(notice, who); -#else /* !OLD_COMPAT */ - ack(notice, who); -#endif /* OLD_COMPAT */ - subscr_sendlist(notice, auth, who); - return(ZERR_NONE); - } else if (!auth) { -#if 0 - zdbug((LOG_DEBUG,"unauth ctrl_disp")); -#endif - if (server == me_server) - clt_ack(notice, who, AUTH_FAILED); - return(ZERR_NONE); - } - - /* the rest of the expected opcodes modify state; check for - unlocked host first */ - host = hostm_find_host(&who->sin_addr); - if (host && host->zh_locked) - return(ZSRV_REQUEUE); - - wantdefs = strcmp (opcode, CLIENT_SUBSCRIBE_NODEFS); - if (!wantdefs || !strcmp (opcode, CLIENT_SUBSCRIBE)) { - /* subscription notice */ - if (!(client = client_which_client(who, notice))) { - if ((retval = client_register(notice, - who, - &client, - server, - wantdefs)) != ZERR_NONE) - { - syslog(LOG_NOTICE, - "subscr. register %s/%s/%d failed: %s", - notice->z_sender, - inet_ntoa(who->sin_addr), - ntohs(notice->z_port), - error_message(retval)); - if (server == me_server) { - if (retval == ZSRV_BADSUBPORT) { - clt_ack(notice, who, AUTH_FAILED); - } else - hostm_deathgram(who, me_server); - } - return(ZERR_NONE); - } - if (!(client = client_which_client(who, notice))) { - syslog(LOG_CRIT, "subscr reg. failure"); - abort(); - } - } - if (strcmp (client->zct_principal->string, notice->z_sender)) { - /* you may only subscribe for your own clients */ - if (server == me_server) - clt_ack(notice, who, AUTH_FAILED); - return(ZERR_NONE); - } -#ifdef KERBEROS - /* in case it's changed */ - (void) memcpy((caddr_t) client->zct_cblock, (caddr_t) ZGetSession(), - sizeof(C_Block)); -#endif - if ((retval = subscr_subscribe(client,notice)) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr failed: %s", - error_message(retval)); - if (server == me_server) - nack(notice, who); - return(ZERR_NONE); - } - } else if (!strcmp(opcode, CLIENT_UNSUBSCRIBE)) { - if ((client = client_which_client(who,notice)) != NULLZCNT) { - if (strcmp(client->zct_principal->string, notice->z_sender)) { - /* you may only cancel for your own clients */ - if (server == me_server) - clt_ack(notice, who, AUTH_FAILED); - return(ZERR_NONE); - } -#if 0 - if (zdebug) { - if (server == me_server) - syslog (LOG_DEBUG, - "subscription cancel for %s/%d\n", - inet_ntoa (who->sin_addr), - ntohs (who->sin_port)); - else - syslog (LOG_DEBUG, - "subscription cancel for %s/%d from %s\n", - inet_ntoa (who->sin_addr), - ntohs (who->sin_port), - server->addr); - } -#endif - (void) subscr_cancel(who, notice); - } else { - nack(notice, who); - return(ZERR_NONE); - } - } else if (!strcmp(opcode, CLIENT_CANCELSUB)) { - /* canceling subscriptions implies I can punt info about - this client */ - if ((client = client_which_client(who,notice)) != NULLZCNT) { - if (strcmp(client->zct_principal->string, notice->z_sender)) { - /* you may only cancel for your own clients */ - if (server == me_server) - clt_ack(notice, who, AUTH_FAILED); - return(ZERR_NONE); - } - if (host) { - /* don't flush locations here, let him - do it explicitly */ -#if 0 - zdbug((LOG_DEBUG, "cancelsub clt_dereg %s/%d", - inet_ntoa (who->sin_addr), - ntohs (who->sin_port))); -#endif - hostm_lose_ignore(client); - (void) client_deregister(client, host, 0); - } - - } - if (!client || !host) { -#if 0 - zdbug((LOG_DEBUG,"can_sub not found client")); -#endif - if (server == me_server) - nack(notice, who); - return(ZERR_NONE); - } - } else { - syslog(LOG_WARNING, "unknown ctl opcode %s", opcode); - if (server == me_server) - nack(notice, who); - return(ZERR_NONE); - } - - if (server == me_server) { - ack(notice, who); - server_forward(notice, auth, who); - } - return(ZERR_NONE); -} - - diff --git a/server/hostm.c b/server/hostm.c deleted file mode 100644 index 4a029ea..0000000 --- a/server/hostm.c +++ /dev/null @@ -1,1045 +0,0 @@ -/* This file is part of the Project Athena Zephyr Notification System. - * It contains functions for communicating with the HostManager. - * - * Created by: John T. Kohl - * - * $Source$ - * $Author$ - * - * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology. - * For copying and distribution information, see the file - * "mit-copyright.h". - */ - -#include <zephyr/mit-copyright.h> - -#ifndef lint -#ifndef SABER -static char rcsid_hostm_c[] = "$Id$"; -#endif -#endif - -#include "zserver.h" -#include <sys/socket.h> /* for AF_INET */ - -/* - * - * External functions: - * - * void hostm_dispatch(notice, auth, who, server) - * ZNotice_t *notice; - * int auth; - * struct sockaddr_in *who; - * ZServerDesc_t *server; - * - * void hostm_flush(host, server) - * ZHostList_t *host; - * ZServerDesc_t *server; - * - * void hostm_transfer(host, server) - * ZHostList_t *host; - * ZServerDesc_t *server; - * - * ZHostList_t *hostm_find_host(addr) - * struct in_addr *addr; - * - * ZServerDesc_t *hostm_find_server(addr) - * struct in_addr *addr; - * - * void hostm_shutdown() - * - * void hostm_losing(client, host) - * ZClient_t *client; - * ZHostList_t *host; - * - * void hostm_deathgram(sin, server) - * struct sockaddr_in *sin; - * ZServerDesc_t *server; - * - * void hostm_dump_hosts(fp) - * FILE *fp; - */ - -/* - * This module maintains two important structures. - * all_hosts is an array of all currently known hosts, and which server - * is responsible for that host. This list is kept sorted by IP address - * so that lookups can be fast (binary search). num_hosts contains the - * number of hosts to be found in the array. - * - * The losing hosts list is a linked list of all the clients (and their hosts) - * whose existence is in doubt. Any host on this list has already been sent - * a ping and is expected to reply immediately. - * As usual, the first element of the list is a placeholder header so we - * know when the list has been completely scanned. - */ - -struct hostlist { - ZHostList_t *host; /* ptr to host struct */ - int server_index; /* index of server in the table */ -}; - -typedef struct _losinghost { - struct _losinghost *q_forw; - struct _losinghost *q_back; - struct _ZHostList_t *lh_host; - timer lh_timer; - struct _ZClient_t *lh_client; -} losinghost; - -#define NULLHLT ((struct hostlist *) 0) - -static struct hostlist *all_hosts; - -static int num_hosts = 0; /* number of hosts in all_hosts */ -static long lose_timo = LOSE_TIMO; - -static losinghost *losing_hosts; /* queue of pings for hosts we - doubt are really there */ - -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -static void host_detach P((register ZHostList_t *host, ZServerDesc_t *server)), - insert_host P((ZHostList_t *host, ZServerDesc_t *server)), - remove_host P((ZHostList_t *host)); -static void host_not_losing P((struct sockaddr_in *who)), - host_lost P((void *which)), - ping P((struct sockaddr_in *sin)); -static Code_t host_attach P((struct sockaddr_in *who, ZServerDesc_t *server)); - -#undef P - -/* - * We received a HostManager packet. process accordingly. - */ - -/*ARGSUSED*/ -Code_t -hostm_dispatch(notice, auth, who, server) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - ZServerDesc_t *server; -{ - ZServerDesc_t *owner; - ZHostList_t *host = NULLZHLT; - char *opcode = notice->z_opcode; - Code_t retval; - -#if 0 - zdbug((LOG_DEBUG,"hm_disp")); -#endif - - host = hostm_find_host(&who->sin_addr); - if (host && host->zh_locked) - return(ZSRV_REQUEUE); - - if (notice->z_kind == HMACK) { - host_not_losing(who); - return(ZERR_NONE); - } else if (notice->z_kind != HMCTL) { -#if 0 - zdbug((LOG_DEBUG, "bogus HM packet")); -#endif - clt_ack(notice, who, AUTH_FAILED); - return(ZERR_NONE); - } - owner = hostm_find_server(&who->sin_addr); - if (!strcmp(opcode, HM_ATTACH)) { -#if 0 - zdbug((LOG_DEBUG,"attach %s",inet_ntoa(who))); -#endif - if (owner == server) { -#if 0 - zdbug((LOG_DEBUG,"no change")); -#endif - /* Same server owns him. do nothing */ - } else if (owner) { - /* He has switched servers. - he was lost but has asked server to work for him. - We need to transfer him to server */ -#if 0 - zdbug((LOG_DEBUG,"hm_disp transfer")); -#endif - hostm_transfer(host, server); - } else { - /* no owner. attach him to server. */ - if ((retval = host_attach(who, server)) - != ZERR_NONE) { - syslog(LOG_WARNING, "hattach failed: %s", - error_message(retval)); - return(retval); - } - - } - if (server == me_server) { - server_forward(notice, auth, who); - ack(notice, who); - } - } else if (!strcmp(opcode, HM_BOOT)) { -#if 0 - zdbug((LOG_DEBUG, "boot %s (server %s)", - inet_ntoa(who->sin_addr), - server->addr)); -#endif - /* Booting is just like flushing and attaching */ - if (owner) /* if owned, flush */ - hostm_flush(host, owner); - if ((retval = host_attach(who, server)) != ZERR_NONE) { - syslog(LOG_WARNING, "hattach failed: %s", - error_message(retval)); - return(retval); - } - if (server == me_server) { - server_forward(notice, auth, who); - ack(notice, who); - } - } else if (!strcmp(opcode, HM_FLUSH)) { -#if 0 - zdbug((LOG_DEBUG, "hm_flush %s (server %s)", - inet_ntoa(who->sin_addr), - server->addr)); -#endif - if (!owner) - return(ZERR_NONE); - /* flush him */ - hostm_flush(host, owner); - if (server == me_server) - server_forward(notice, auth, who); - } else if (!strcmp(opcode, HM_DETACH)) { -#if 0 - zdbug((LOG_DEBUG, "hm_detach %s",inet_ntoa(who_sin_addr))); -#endif - /* ignore it */ - } else { - syslog(LOG_WARNING, "hm_disp: unknown opcode %s",opcode); - return(ZERR_NONE); - } - return(ZERR_NONE); -} - -/* - * Flush all information about this host. Remove any losing host entries, - * deregister all the clients, flush any user locations, and remove the host - * from its server. - * The caller is responsible for informing other servers of this flush - * (if appropriate). - */ - -void -hostm_flush(host, server) - ZHostList_t *host; - ZServerDesc_t *server; -{ - register ZClientList_t *clist = NULLZCLT, *clt; - losinghost *lhp, *lhp2; - - START_CRITICAL_CODE; - - if (!host) { - syslog(LOG_WARNING, "null host flush"); - return; - } - -#if 0 - zdbug ((LOG_DEBUG,"hostm_flush %s", inet_ntoa (host->zh_addr.sin_addr))); -#endif - - if (losing_hosts) - for (lhp = losing_hosts->q_forw; - lhp != losing_hosts;) - if (lhp->lh_host == host) { - lhp2 = lhp->q_back; - timer_reset(lhp->lh_timer); - xremque(lhp); - xfree(lhp); - lhp = lhp2->q_forw; - } else - lhp = lhp->q_forw; - - if ((clist = host->zh_clients) != NULLZCLT) { - for (clt = clist->q_forw; clt != clist; clt = clist->q_forw) { - /* client_deregister frees this client & subscriptions - & locations and remque()s the client */ -#if 0 - if (zdebug) - syslog (LOG_DEBUG, "hostm_flush clt_dereg %s/%d", - inet_ntoa(host->zh_addr.sin_addr), - ntohs (clt->zclt_client->zct_sin.sin_port)); -#endif - client_deregister(clt->zclt_client, host, 1); - } - } - - uloc_hflush(&host->zh_addr.sin_addr); - host_detach(host, server); - - END_CRITICAL_CODE; - - return; -} - -/* - * send a shutdown to each of our hosts - */ - -void -hostm_shutdown() -{ - register ZHostList_t *hosts = otherservers[me_server_idx].zs_hosts; - register ZHostList_t *host; - int newserver, i; - -#if 0 - zdbug((LOG_DEBUG,"hostm_shutdown")); -#endif - if (!hosts) - return; - - for (i = 0; i < nservers; i++){ - if (i == me_server_idx) continue; - if (otherservers[i].zs_state == SERV_UP) - break; - } - if (i == nservers) /* no other servers are up */ - newserver = 0; - else - newserver = 1; - - /* kill them all */ - for (host = hosts->q_forw; - host != hosts; - host = host->q_forw) { - /* recommend a random, known up server */ - if (newserver) { - do - newserver = (int) (random() % (nservers - 1)) + 1; - while (newserver == limbo_server_idx() || - (otherservers[newserver].zs_state != SERV_UP && - otherservers[newserver].zs_state != SERV_TARDY) || - newserver == me_server_idx); - hostm_deathgram(&host->zh_addr, &otherservers[newserver]); - } else - hostm_deathgram(&host->zh_addr, NULLZSDT); - } - return; -} - - -/* - * The client on the host is not acknowledging any packets. Ping the - * host and set a timeout. - */ - -void -hostm_losing(client, host) - ZClient_t *client; - ZHostList_t *host; -{ - losinghost *newhost; - -#if 0 - zdbug((LOG_DEBUG,"losing host")); -#endif - if (!losing_hosts) { - if (!(losing_hosts = (losinghost *) - xmalloc(sizeof(losinghost)))) { - syslog(LOG_ERR, "no mem losing host"); - return; - } - losing_hosts->q_forw = losing_hosts->q_back = losing_hosts; - } - for (newhost = losing_hosts->q_forw; - newhost != losing_hosts; - newhost = newhost->q_forw) - if (newhost->lh_client == client) { -#if 0 - zdbug((LOG_DEBUG,"clt already losing")); -#endif - return; - } - if (!(newhost = (losinghost *) xmalloc(sizeof(losinghost)))) { - syslog(LOG_ERR, "no mem losing host 2"); - return; - } - - /* send a ping */ - ping(&host->zh_addr); - newhost->lh_host = host; - newhost->lh_client = client; - newhost->lh_timer = timer_set_rel(lose_timo, host_lost, (void *) newhost); - xinsque(newhost, losing_hosts); - return; -} - -/* - * The host did not respond to the ping, so we punt him - */ - -static void -host_lost(arg) - void* arg; -{ - losinghost *which = (losinghost *) arg; - ZServerDesc_t *server; - ZNotice_t notice; - struct sockaddr_in who; - Code_t retval; - char *buffer; - int len; - - START_CRITICAL_CODE; - - server = hostm_find_server(&which->lh_host->zh_addr.sin_addr); -#if 1 - zdbug ((LOG_DEBUG,"lost host %s (server %s)", - inet_ntoa(which->lh_host->zh_addr.sin_addr), - server ? server->addr : "<NONE>")); -#endif - - if (!server) { -#if 1 - zdbug((LOG_DEBUG,"no server")); -#endif - xremque(which); - xfree(which); - END_CRITICAL_CODE; - return; - } - xremque(which); - hostm_flush(which->lh_host, server); - - (void) memset((caddr_t)¬ice, 0, sizeof(notice)); - - /* tell other servers to flush this host */ - notice.z_kind = HMCTL; - notice.z_auth = 0; - notice.z_port = hm_port; - notice.z_class = ZEPHYR_CTL_CLASS; - notice.z_class_inst = ZEPHYR_CTL_HM; - notice.z_opcode = HM_FLUSH; - notice.z_sender = "HM"; - notice.z_recipient = ""; - notice.z_default_format = ""; - notice.z_num_other_fields = 0; - notice.z_message_len = 0; - - /* generate the other fields */ - retval = ZFormatNotice(¬ice, &buffer, &len, ZNOAUTH); - if (retval != ZERR_NONE) - return; - xfree(buffer); - - /* forge a from address */ - (void) memset((char *) &who, 0, sizeof(who)); - who.sin_addr.s_addr = which->lh_host->zh_addr.sin_addr.s_addr; - who.sin_port = hm_port; - who.sin_family = AF_INET; - - server_forward(¬ice, 0, &who); /* unauthentic */ - - xfree(which); - - END_CRITICAL_CODE; - - return; -} - -/* - * The host responded to the ping, so we flush the losing clients on this host. - */ - -static void -host_not_losing(who) - struct sockaddr_in *who; -{ - losinghost *lhp, *lhp2; - - if (!losing_hosts) - return; - - START_CRITICAL_CODE; - - for (lhp = losing_hosts->q_forw; - lhp != losing_hosts;) - if (lhp->lh_host->zh_addr.sin_addr.s_addr == who->sin_addr.s_addr) { - /* go back, since remque will change things */ - lhp2 = lhp->q_back; - timer_reset(lhp->lh_timer); -#if 1 - if (zdebug || 1) - syslog (LOG_DEBUG,"lost client %s/%d", - inet_ntoa(lhp->lh_client->zct_sin.sin_addr), - ntohs(lhp->lh_client->zct_sin.sin_port)); -#endif - /* deregister all subscriptions, and flush locations - associated with the client. */ -#if 0 - if (zdebug) - syslog(LOG_DEBUG,"h_not_lose clt_dereg"); -#endif - server_kill_clt(lhp->lh_client); - client_deregister(lhp->lh_client, lhp->lh_host, 1); - xremque(lhp); - xfree(lhp); - /* now that the remque adjusted the linked list, - we go forward again */ - lhp = lhp2->q_forw; - } else - lhp = lhp->q_forw; - - END_CRITICAL_CODE; - - return; -} - -/* - * A client is being de-registered, so remove it from the losing_host list, - * if it is there. - */ - -void -hostm_lose_ignore(client) - ZClient_t *client; -{ - losinghost *lhp, *lhp2; - - if (!losing_hosts) - return; - - START_CRITICAL_CODE; - - for (lhp = losing_hosts->q_forw; - lhp != losing_hosts;) - /* if client matches, remove it */ - if (lhp->lh_client == client) { - /* go back, since remque will change things */ - lhp2 = lhp->q_back; - timer_reset(lhp->lh_timer); -#if 0 - zdbug((LOG_DEBUG,"hm_l_ign client %s/%d", - inet_ntoa(client->zct_sin), - ntohs(client->zct_sin.sin_port))); -#endif - xremque(lhp); - xfree(lhp); - /* now that the remque adjusted the linked list, - we go forward again */ - lhp = lhp2->q_forw; - } else - lhp = lhp->q_forw; - - END_CRITICAL_CODE; - - return; -} - -/* - * transfer this host to server's ownership. The caller must update the - * other servers. - */ - -void -hostm_transfer(host, server) - ZHostList_t *host; - ZServerDesc_t *server; -{ - /* we need to unlink and relink him, and change the table entry */ -#if 1 - if (zdebug) - syslog (LOG_DEBUG, "hostm_transfer %s to %s", - inet_ntoa (host->zh_addr.sin_addr), server->addr); -#endif - - /* is this the same server? */ - if (hostm_find_server(&host->zh_addr.sin_addr) == server) - return; - - START_CRITICAL_CODE; - - /* remove from old server's queue */ - xremque(host); - - /* switch servers in the table */ - remove_host(host); - insert_host(host, server); - - /* insert in our queue */ - xinsque(host, server->zs_hosts); - - END_CRITICAL_CODE; - - return; -} - - -/* - * attach the host with return address in who to the server. - */ - -static Code_t -host_attach(who, server) - struct sockaddr_in *who; - ZServerDesc_t *server; -{ - register ZHostList_t *hlist; - register ZClientList_t *clist; - - START_CRITICAL_CODE; - -#if 0 - if (zdebug) - syslog (LOG_DEBUG, "host_attach %s to %s", - inet_ntoa (who->sin_addr), server->addr); -#endif - /* allocate a header */ - if (!(hlist = (ZHostList_t *) xmalloc(sizeof(ZHostList_t)))) { - syslog(LOG_WARNING, "hm_attach alloc"); - END_CRITICAL_CODE; - return(ENOMEM); - } - /* set up */ - if (!(clist = (ZClientList_t *)xmalloc(sizeof(ZClientList_t)))) { - xfree(hlist); - END_CRITICAL_CODE; - return(ENOMEM); - } - clist->zclt_client = NULLZCNT; - clist->q_forw = clist->q_back = clist; - - hlist->zh_clients = clist; - hlist->zh_addr = *who; - hlist->q_forw = hlist->q_back = hlist; - hlist->zh_locked = 0; - - /* add to table */ - insert_host(hlist, server); - - /* chain in to the end of the list */ - xinsque(hlist, server->zs_hosts->q_back); - - END_CRITICAL_CODE; - - return(ZERR_NONE); -} - -/* - * detach the host at addr from the server - * Warning: this routine assumes all the clients have already been removed - * from this host. - */ - -static void -host_detach(host, server) - register ZHostList_t *host; - ZServerDesc_t *server; -{ - ZServerDesc_t *server2; - - START_CRITICAL_CODE; - - /* undo what we did in host_attach */ - server2 = hostm_find_server (&host->zh_addr.sin_addr); - - if (server2 != server) { - syslog(LOG_WARNING, - "host_detach: wrong server: %s from %s, found %s", - inet_ntoa (host->zh_addr.sin_addr), - server->addr, - server2->addr); - END_CRITICAL_CODE; - return; - } - - - /* all the clients have already been freed */ - xfree(host->zh_clients); - - /* unchain */ - xremque(host); - - /* remove from table */ - remove_host(host); - - xfree(host); - - END_CRITICAL_CODE; - - return; -} - -/* - * Build hostmanager recipient name. - */ -static char * -hm_recipient () -{ - static char *recipient; - char *realm; - - if (recipient) - return recipient; - - realm = ZGetRealm (); - if (!realm) - realm = "???"; - recipient = (char *) xmalloc (strlen (realm) + 4); - strcpy (recipient, "hm@"); - strcat (recipient, realm); - return recipient; -} - -/* - * Send a shutdown message to the HostManager at sin, recommending him to - * use server - */ - -void -hostm_deathgram(sin, server) - struct sockaddr_in *sin; - ZServerDesc_t *server; -{ - Code_t retval; - int shutlen; - ZNotice_t shutnotice; - char *shutpack; - -#if 0 - zdbug((LOG_DEBUG,"deathgram %s",inet_ntoa(*sin))); -#endif - - /* fill in the shutdown notice */ - - shutnotice.z_kind = HMCTL; - shutnotice.z_port = sock_sin.sin_port; /* we are sending it */ - shutnotice.z_class = HM_CTL_CLASS; - shutnotice.z_class_inst = HM_CTL_SERVER; - shutnotice.z_opcode = SERVER_SHUTDOWN; - shutnotice.z_sender = HM_CTL_SERVER; - shutnotice.z_recipient = hm_recipient (); - shutnotice.z_default_format = ""; - shutnotice.z_num_other_fields = 0; - - if (server) { - shutnotice.z_message = server->addr; - shutnotice.z_message_len = strlen(shutnotice.z_message) + 1; -#if 0 - zdbug((LOG_DEBUG, "suggesting %s",shutnotice.z_message)); -#endif - } else { - shutnotice.z_message = NULL; - shutnotice.z_message_len = 0; - } - - if ((retval = ZFormatNotice(&shutnotice, - &shutpack, - &shutlen, - ZNOAUTH)) != ZERR_NONE) { - syslog(LOG_ERR, "hm_shut format: %s",error_message(retval)); - return; - } - if ((retval = ZSetDestAddr(sin)) != ZERR_NONE) { - syslog(LOG_WARNING, "hm_shut set addr: %s", - error_message(retval)); - xfree(shutpack); /* free allocated storage */ - return; - } - /* don't wait for ack! */ - if ((retval = ZSendPacket(shutpack, shutlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "hm_shut xmit: %s", error_message(retval)); - xfree(shutpack); /* free allocated storage */ - return; - } - xfree(shutpack); /* free allocated storage */ - return; -} - -/* - * Send a ping to the HostManager at sin - */ - -static void -ping(sin) - struct sockaddr_in *sin; -{ - Code_t retval; - int shutlen; - ZNotice_t shutnotice; - char *shutpack; - -#if 0 - zdbug((LOG_DEBUG,"ping %s",inet_ntoa(*sin))); -#endif - - /* fill in the shutdown notice */ - - shutnotice.z_kind = HMCTL; - shutnotice.z_port = sock_sin.sin_port; - shutnotice.z_class = HM_CTL_CLASS; - shutnotice.z_class_inst = HM_CTL_SERVER; - shutnotice.z_opcode = SERVER_PING; - shutnotice.z_sender = HM_CTL_SERVER; - shutnotice.z_recipient = hm_recipient (); - shutnotice.z_message = NULL; - shutnotice.z_message_len = 0; - shutnotice.z_default_format = ""; - shutnotice.z_num_other_fields = 0; - - if ((retval = ZFormatNotice(&shutnotice, - &shutpack, - &shutlen, - ZNOAUTH)) != ZERR_NONE) { - syslog(LOG_ERR, "hm_ping format: %s",error_message(retval)); - return; - } - if ((retval = ZSetDestAddr(sin)) != ZERR_NONE) { - syslog(LOG_WARNING, "hm_ping set addr: %s", - error_message(retval)); - xfree(shutpack); /* free allocated storage */ - return; - } - /* don't wait for ack */ - if ((retval = ZSendPacket(shutpack, shutlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "hm_ping xmit: %s", error_message(retval)); - xfree(shutpack); /* free allocated storage */ - return; - } - xfree(shutpack); /* free allocated storage */ - return; -} - -/* - * Routines for maintaining the host array. - */ - -/* - * Binary search on the host table to find this host. - */ - -ZHostList_t * -hostm_find_host(addr) - struct in_addr *addr; -{ - register int i, rlo, rhi; - - if (!all_hosts) - return(NULLZHLT); - - /* i is the current host we are checking */ - /* rlo is the lowest we will still check, rhi is the highest we will - still check */ - - i = num_hosts >> 1; /* start in the middle */ - rlo = 0; - rhi = num_hosts - 1; /* first index is 0 */ - - while ((all_hosts[i].host)->zh_addr.sin_addr.s_addr != addr->s_addr) { - if ((all_hosts[i].host)->zh_addr.sin_addr.s_addr < addr->s_addr) - rlo = i + 1; - else - rhi = i - 1; - if (rhi - rlo < 0) - return(NULLZHLT); - i = (rhi + rlo) >> 1; /* split the diff */ - } - return(all_hosts[i].host); -} - -/* - * Binary search on the host table to find this host's server. - */ - -ZServerDesc_t * -hostm_find_server(addr) - struct in_addr *addr; -{ - register int i, rlo, rhi; - - if (!all_hosts) - return(NULLZSDT); - - /* i is the current host we are checking */ - /* rlo is the lowest we will still check, rhi is the highest we will - still check */ - - i = num_hosts >> 1; /* start in the middle */ - rlo = 0; - rhi = num_hosts - 1; /* first index is 0 */ - - while ((all_hosts[i].host)->zh_addr.sin_addr.s_addr != addr->s_addr) { - if ((all_hosts[i].host)->zh_addr.sin_addr.s_addr < addr->s_addr) - rlo = i + 1; - else - rhi = i - 1; - if (rhi - rlo < 0) - return(NULLZSDT); - i = (rhi + rlo) >> 1; /* split the diff */ - } - return(&otherservers[all_hosts[i].server_index]); -} - -/* - * Insert the host and server into the sorted array of hosts. - */ - -static void -insert_host(host, server) - ZHostList_t *host; - ZServerDesc_t *server; -{ - struct hostlist *oldlist; - register int i = 0; - -#if 0 - zdbug ((LOG_DEBUG,"insert_host %s %s", - inet_ntoa(host->zh_addr.sin_addr), server->addr)); -#endif - if (hostm_find_host(&host->zh_addr.sin_addr)) - return; - - START_CRITICAL_CODE; - - num_hosts++; - oldlist = all_hosts; - - if (!(all_hosts = (struct hostlist *) xmalloc(num_hosts * sizeof(struct hostlist)))) { - syslog(LOG_CRIT, "insert_host: nomem"); - abort(); - } - - if (!oldlist) { /* this is the first */ - all_hosts[0].host = host; - all_hosts[0].server_index = server - otherservers; - END_CRITICAL_CODE; - return; - } - - /* copy old pointers */ - while ((i < (num_hosts - 1)) && - ((oldlist[i].host)->zh_addr.sin_addr.s_addr < host->zh_addr.sin_addr.s_addr)) { - all_hosts[i] = oldlist[i]; - i++; - } - /* add this one */ - all_hosts[i].host = host; - all_hosts[i++].server_index = server - otherservers; - - /* copy the rest */ - while (i < num_hosts) { - all_hosts[i] = oldlist[i - 1]; - i++; - } - xfree(oldlist); - - END_CRITICAL_CODE; - -#if defined (DEBUG) && 0 - if (zdebug) { - register int i = 0; - for (i = 0; i < num_hosts; i++) - syslog(LOG_DEBUG, "%d: %s %s",i, - inet_ntoa ((all_hosts[i].host)->zh_addr.sin_addr), - otherservers[all_hosts[i].server_index]->addr); - } -#endif - return; -} - -/* - * remove the host from the array of known hosts. - */ - -static void -remove_host(host) - ZHostList_t *host; -{ - struct hostlist *oldlist; - register int i = 0; - -#if 0 - zdbug((LOG_DEBUG,"remove_host %s", inet_ntoa(host->zh_addr.sin_addr))); -#endif - if (!hostm_find_host(&host->zh_addr.sin_addr)) - return; - - START_CRITICAL_CODE; - - if (--num_hosts == 0) { -#if 0 - zdbug((LOG_DEBUG,"last host")); -#endif - xfree (all_hosts); - all_hosts = NULLHLT; - END_CRITICAL_CODE; - return; - } - - oldlist = all_hosts; - - if (!(all_hosts = (struct hostlist *) xmalloc(num_hosts * sizeof(struct hostlist)))) { - syslog(LOG_CRIT, "remove_host: nomem"); - abort(); - } - - /* copy old pointers */ - while (i < num_hosts && (oldlist[i].host)->zh_addr.sin_addr.s_addr < host->zh_addr.sin_addr.s_addr) { - all_hosts[i] = oldlist[i]; - i++; - } - - i++; /* skip over this one */ - - /* copy the rest */ - while (i <= num_hosts) { - all_hosts[i - 1] = oldlist[i]; - i++; - } - xfree (oldlist); - - END_CRITICAL_CODE; - - return; -} - -/* - * Assumes that SIGFPE is blocked when called; this is true if called from a - * signal handler - */ - -void -hostm_dump_hosts(fp) - FILE *fp; -{ - register int i; - for (i = 0; i < num_hosts; i++) { - (void) fprintf(fp, "%s/%d:\n", - inet_ntoa((all_hosts[i].host)->zh_addr.sin_addr), - all_hosts[i].server_index); - client_dump_clients(fp,(all_hosts[i].host)->zh_clients); - } - return; -} - -/* - * Readjust server-array indices according to the supplied new vector. - */ - -void -hostm_renumber_servers (srv) - int *srv; -{ - int i; - for (i = 0; i < num_hosts; i++) { - int idx = srv[all_hosts[i].server_index]; - if (idx < 0) { - syslog (LOG_ERR, "hostm_renumber_servers error: [%d] = %d", - all_hosts[i].server_index, idx); - idx = 0; - } - all_hosts[i].server_index = idx; - } -} diff --git a/server/kopt.c b/server/kopt.c index 5d62688..3bcaa57 100644 --- a/server/kopt.c +++ b/server/kopt.c @@ -16,24 +16,22 @@ * Kerberos: krb_conf.h,v 4.0 89/01/23 09:59:27 jtkohl Exp */ +#include <zephyr/mit-copyright.h> +#include "zserver.h" + #ifndef lint #ifndef SABER -static char *rcsid_rd_req_c = +static const char *rcsid_rd_req_c = "$Id$"; #endif /* lint */ #endif /* SABER */ -#ifdef KERBEROS +#ifdef ZEPHYR_USES_KERBEROS #ifndef NOENCRYPTION -#include <zephyr/mit-copyright.h> -#include <zephyr/zephyr.h> -#include <stdio.h> -#include <krb.h> -#include "zserver.h" - /* Byte ordering */ -static int krbONE; +#undef HOST_BYTE_ORDER +static int krbONE = 1; #define HOST_BYTE_ORDER (* (char *) &krbONE) #define KRB_PROT_VERSION 4 @@ -64,9 +62,6 @@ static int krbONE; #define KERB_ERR_PRINCIPAL_NOT_UNIQUE 9 #define KERB_ERR_NULL_KEY 10 -#include <sys/time.h> -#include <string.h> - extern int krb_ap_req_debug; extern struct timeval t_local; @@ -97,34 +92,26 @@ typedef struct { } KeySchedRec; static KeySchedRec scheds[HASH_SIZE_1][HASH_SIZE_2]; -#ifdef __STDC__ -Sched* check_key_sched_cache (des_cblock key) -#else -Sched* check_key_sched_cache (key) - des_cblock key; -#endif +Sched *check_key_sched_cache(key) + des_cblock key; { unsigned int hash_value = key[0] + key[1] * 256; KeySchedRec *rec = scheds[hash_value % HASH_SIZE_1]; int i; - for (i = HASH_SIZE_2 - 1; i >= 0; i--) - if (rec[i].last_time_used - && key[0] == rec[i].key[0] - && !memcmp (key, rec[i].key, sizeof (des_cblock))) { + for (i = HASH_SIZE_2 - 1; i >= 0; i--) { + if (rec[i].last_time_used && key[0] == rec[i].key[0] + && !memcmp(key, rec[i].key, sizeof(des_cblock))) { rec[i].last_time_used = last_use++; return &rec[i].schedule; } + } return 0; } -#ifdef __STDC__ -void add_to_key_sched_cache (des_cblock key, Sched* sched) -#else -void add_to_key_sched_cache (key, sched) - des_cblock key; - Sched* sched; -#endif +void add_to_key_sched_cache(key, sched) + des_cblock key; + Sched *sched; { unsigned int hash_value = key[0] + key[1] * 256; KeySchedRec *rec = scheds[hash_value % HASH_SIZE_1]; @@ -138,7 +125,7 @@ void add_to_key_sched_cache (key, sched) if (rec[i].last_time_used < rec[oldest].last_time_used) oldest = i; } - (void) memcpy (rec[oldest].key, key, sizeof (des_cblock)); + memcpy (rec[oldest].key, key, sizeof(des_cblock)); rec[oldest].schedule = *sched; rec[oldest].last_time_used = last_use++; } @@ -178,7 +165,7 @@ krb_set_key(key,cvt) int cvt; { #ifdef NOENCRYPTION - (void) memset(serv_key, 0, sizeof(serv_key)); + memset(serv_key, 0, sizeof(serv_key)); return KSUCCESS; #else /* Encrypt */ Sched *s; @@ -187,15 +174,15 @@ krb_set_key(key,cvt) if (cvt) string_to_key(key,serv_key); else - (void) memcpy((char *)serv_key,key,8); + memcpy((char *)serv_key,key,8); s = check_key_sched_cache (serv_key); if (s) { serv_ksched = *s; return 0; } - ret = des_key_sched (serv_key, serv_ksched.s); - add_to_key_sched_cache (serv_key, &serv_ksched); + ret = des_key_sched(serv_key, serv_ksched.s); + add_to_key_sched_cache(serv_key, &serv_ksched); return ret; #endif /* NOENCRYPTION */ } @@ -242,18 +229,19 @@ krb_set_key(key,cvt) * Mutual authentication is not implemented. */ +int krb_rd_req(authent,service,instance,from_addr,ad,fn) - register KTEXT authent; /* The received message */ - char *service; /* Service name */ - char *instance; /* Service instance */ - long from_addr; /* Net address of originating host */ - AUTH_DAT *ad; /* Structure to be filled in */ - char *fn; /* Filename to get keys from */ + KTEXT authent; /* The received message */ + char *service; /* Service name */ + char *instance; /* Service instance */ + unsigned KRB_INT32 from_addr; /* Net address of originating host */ + AUTH_DAT *ad; /* Structure to be filled in */ + char *fn; /* Filename to get keys from */ { KTEXT_ST ticket; /* Temp storage for ticket */ KTEXT tkt = &ticket; KTEXT_ST req_id_st; /* Temp storage for authenticator */ - register KTEXT req_id = &req_id_st; + KTEXT req_id = &req_id_st; char realm[REALM_SZ]; /* Realm of issuing kerberos */ Sched seskey_sched, *sched; /* Key sched for session key */ @@ -265,7 +253,7 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) char r_realm[REALM_SZ]; /* Client realm from authenticator */ unsigned int r_time_ms; /* Fine time from authenticator */ unsigned long r_time_sec; /* Coarse time from authenticator */ - register char *ptr; /* For stepping through */ + char *ptr; /* For stepping through */ unsigned long delta_t; /* Time in authenticator - local time */ long tkt_age; /* Age of ticket */ int swap_bytes; /* Need to swap bytes? */ @@ -283,7 +271,7 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) /* check version */ if (KRB_PROT_VERSION != (unsigned int) *ptr++) - return(RD_AP_VERSION); + return RD_AP_VERSION; /* byte order */ swap_bytes = 0; @@ -293,12 +281,12 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) /* check msg type */ mutual = 0; switch (*ptr++ & ~1) { - case AUTH_MSG_APPL_REQUEST: + case AUTH_MSG_APPL_REQUEST: break; - case AUTH_MSG_APPL_REQUEST_MUTUAL: + case AUTH_MSG_APPL_REQUEST_MUTUAL: mutual++; break; - default: + default: return(RD_AP_MSG_TYPE); } @@ -309,7 +297,7 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) mutual = 0; #endif /* lint */ s_kvno = *ptr++; /* get server key version */ - (void) strcpy(realm,ptr); /* And the realm of the issuing KDC */ + strcpy(realm,ptr); /* And the realm of the issuing KDC */ ptr += strlen(ptr) + 1; /* skip the realm "hint" */ /* @@ -320,85 +308,90 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) * from the ticket file. If "fn" is the null string, use the * default ticket file. */ - if (fn && (strcmp(st_nam,service) || strcmp(st_inst,instance) || - strcmp(st_rlm,realm) || (st_kvno != s_kvno))) { - if (*fn == 0) fn = KEYFILE; + if (fn && (strcmp(st_nam,service) != 0 || strcmp(st_inst,instance) != 0 || + strcmp(st_rlm,realm) != 0 || (st_kvno != s_kvno))) { + if (*fn == 0) + fn = KEYFILE; st_kvno = s_kvno; #ifndef NOENCRYPTION - if (read_service_key(service,instance,realm,(int) s_kvno, - fn,(char *)skey)) + if (read_service_key(service,instance,realm, (int) s_kvno, + fn, (char *) skey)) return(RD_AP_UNDEC); - if ((status = krb_set_key((char *)skey,0)) != 0) + status = krb_set_key((char *) skey, 0); + if (status != 0) return(status); #endif /* !NOENCRYPTION */ - (void) strcpy(st_rlm,realm); - (void) strcpy(st_nam,service); - (void) strcpy(st_inst,instance); + strcpy(st_rlm,realm); + strcpy(st_nam,service); + strcpy(st_inst,instance); } /* Get ticket from authenticator */ tkt->length = (int) *ptr++; if ((tkt->length + (ptr+1 - (char *) authent->dat)) > authent->length) - return(RD_AP_MODIFIED); - (void) memcpy((char *)(tkt->dat),ptr+1,tkt->length); + return RD_AP_MODIFIED; + memcpy(tkt->dat, ptr + 1, tkt->length); if (krb_ap_req_debug) - log("ticket->length: %d",tkt->length); + krb_log("ticket->length: %d", tkt->length); #ifndef NOENCRYPTION /* Decrypt and take apart ticket */ #endif - if (decomp_ticket(tkt,&ad->k_flags,ad->pname,ad->pinst,ad->prealm, - &(ad->address),ad->session, &(ad->life), - &(ad->time_sec),sname,iname,serv_key,serv_ksched.s)) - return(RD_AP_UNDEC); + if (decomp_ticket(tkt, &ad->k_flags, ad->pname, ad->pinst, ad->prealm, + &(ad->address), ad->session, &(ad->life), + &(ad->time_sec), sname, iname, serv_key, serv_ksched.s)) + return RD_AP_UNDEC; if (krb_ap_req_debug) { - log("Ticket Contents."); - log(" Aname: %s.%s",ad->pname, - ((int)*(ad->prealm) ? ad->prealm : "Athena")); - log(" Service: %s%s%s",sname,((int)*iname ? "." : ""),iname); + krb_log("Ticket Contents."); + krb_log(" Aname: %s.%s",ad->pname, + ((int)*(ad->prealm) ? ad->prealm : "Athena")); + krb_log(" Service: %s%s%s", sname, ((int)*iname ? "." : ""), iname); } /* Extract the authenticator */ req_id->length = (int) *(ptr++); if ((req_id->length + (ptr + tkt->length - (char *) authent->dat)) > authent->length) - return(RD_AP_MODIFIED); - (void) memcpy((char *)(req_id->dat),ptr + tkt->length, req_id->length); + return RD_AP_MODIFIED; + memcpy(req_id->dat, ptr + tkt->length, req_id->length); #ifndef NOENCRYPTION /* And decrypt it with the session key from the ticket */ - if (krb_ap_req_debug) log("About to decrypt authenticator"); - sched = check_key_sched_cache (ad->session); + if (krb_ap_req_debug) + krb_log("About to decrypt authenticator"); + sched = check_key_sched_cache(ad->session); if (!sched) { sched = &seskey_sched; - key_sched (ad->session, seskey_sched.s); - add_to_key_sched_cache (ad->session, &seskey_sched); + key_sched(ad->session, seskey_sched.s); + add_to_key_sched_cache(ad->session, &seskey_sched); } /* can't do much to optimize this... */ - pcbc_encrypt((C_Block *)req_id->dat,(C_Block *)req_id->dat, - (long) req_id->length, sched->s, ad->session,DES_DECRYPT); - if (krb_ap_req_debug) log("Done."); + pcbc_encrypt((C_Block *) req_id->dat, (C_Block *) req_id->dat, + (long) req_id->length, sched->s, ad->session, DES_DECRYPT); + if (krb_ap_req_debug) + krb_log("Done."); #endif /* NOENCRYPTION */ #define check_ptr() if ((ptr - (char *) req_id->dat) > req_id->length) return(RD_AP_MODIFIED); ptr = (char *) req_id->dat; - (void) strcpy(r_aname,ptr); /* Authentication name */ - ptr += strlen(r_aname)+1; + strcpy(r_aname,ptr); /* Authentication name */ + ptr += strlen(r_aname) + 1; check_ptr(); - (void) strcpy(r_inst,ptr); /* Authentication instance */ - ptr += strlen(r_inst)+1; + strcpy(r_inst,ptr); /* Authentication instance */ + ptr += strlen(r_inst) + 1; check_ptr(); - (void) strcpy(r_realm,ptr); /* Authentication name */ - ptr += strlen(r_realm)+1; + strcpy(r_realm,ptr); /* Authentication name */ + ptr += strlen(r_realm) + 1; check_ptr(); - (void) memcpy((char *)&ad->checksum,ptr,4); /* Checksum */ + memcpy(&ad->checksum, ptr, 4); /* Checksum */ ptr += 4; check_ptr(); - if (swap_bytes) swap_u_long(ad->checksum); + if (swap_bytes) + swap_u_long(ad->checksum); r_time_ms = *(ptr++); /* Time (fine) */ #ifdef lint /* XXX r_time_ms is set but not used. why??? */ @@ -408,61 +401,102 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) #endif /* lint */ check_ptr(); /* assume sizeof(r_time_sec) == 4 ?? */ - (void) memcpy((char *)&r_time_sec,ptr,4); /* Time (coarse) */ - if (swap_bytes) swap_u_long(r_time_sec); + memcpy(&r_time_sec,ptr,4); /* Time (coarse) */ + if (swap_bytes) + swap_u_long(r_time_sec); /* Check for authenticity of the request */ if (krb_ap_req_debug) - log("Pname: %s %s",ad->pname,r_aname); + krb_log("Pname: %s %s",ad->pname,r_aname); if (strcmp(ad->pname,r_aname) != 0) - return(RD_AP_INCON); + return RD_AP_INCON; if (strcmp(ad->pinst,r_inst) != 0) - return(RD_AP_INCON); + return RD_AP_INCON; if (krb_ap_req_debug) - log("Realm: %s %s",ad->prealm,r_realm); - if ((strcmp(ad->prealm,r_realm) != 0)) - return(RD_AP_INCON); + krb_log("Realm: %s %s", ad->prealm, r_realm); + if (strcmp(ad->prealm,r_realm) != 0) + return RD_AP_INCON; if (krb_ap_req_debug) - log("Address: %d %d",ad->address,from_addr); + krb_log("Address: %d %d", ad->address, from_addr); if (from_addr && (ad->address != from_addr)) - return(RD_AP_BADD); + return RD_AP_BADD; delta_t = abs((int)(t_local.tv_sec - r_time_sec)); if (delta_t > CLOCK_SKEW) { - (void) gettimeofday(&t_local, (struct timezone *)0); + gettimeofday(&t_local, NULL); delta_t = abs((int)(t_local.tv_sec - r_time_sec)); if (delta_t > CLOCK_SKEW) { - if (krb_ap_req_debug) - log("Time out of range: %d - %d = %d", - t_local.tv_sec,r_time_sec,delta_t); - return(RD_AP_TIME); + if (krb_ap_req_debug) { + krb_log("Time out of range: %d - %d = %d", + t_local.tv_sec, r_time_sec, delta_t); + } + return RD_AP_TIME; } } /* Now check for expiration of ticket */ tkt_age = t_local.tv_sec - ad->time_sec; - if (krb_ap_req_debug) - log("Time: %d Issue Date: %d Diff: %d Life %x", - t_local.tv_sec,ad->time_sec,tkt_age,ad->life); + if (krb_ap_req_debug) { + krb_log("Time: %d Issue Date: %d Diff: %d Life %x", + t_local.tv_sec, ad->time_sec, tkt_age, ad->life); + } if (t_local.tv_sec < ad->time_sec) { - if ((ad->time_sec - t_local.tv_sec) > CLOCK_SKEW) - return(RD_AP_NYV); + if (ad->time_sec - t_local.tv_sec > CLOCK_SKEW) + return RD_AP_NYV; + } else if (t_local.tv_sec - ad->time_sec > 5 * 60 * ad->life) { + return RD_AP_EXP; } - else if ((t_local.tv_sec - ad->time_sec) > 5 * 60 * ad->life) - return(RD_AP_EXP); /* All seems OK */ ad->reply.length = 0; - return(RD_AP_OK); + return RD_AP_OK; } #endif /* NOENCRYPTION */ +int +krb_find_ticket(authent, ticket) + KTEXT authent, ticket; +{ + char *ptr; /* For stepping through */ + + /* Check for bogus length. */ + if (authent->length <= 0) + return RD_AP_MODIFIED; + + ptr = (char *) authent->dat; + + /* check version */ + if (KRB_PROT_VERSION != (unsigned int) *ptr++) + return RD_AP_VERSION; + + /* Make sure msg type is ok. */ + switch (*ptr++ & ~1) { + case AUTH_MSG_APPL_REQUEST: + case AUTH_MSG_APPL_REQUEST_MUTUAL: + break; + default: + return RD_AP_MSG_TYPE; + } + + *ptr++; /* skip server key version */ + ptr += strlen(ptr) + 1; /* skip the realm "hint" */ + + /* Get ticket from authenticator */ + ticket->length = (int) *ptr++; + if ((ticket->length + (ptr + 1 - (char *) authent->dat)) > authent->length) + return RD_AP_MODIFIED; + memcpy((char *)(ticket->dat),ptr+1,ticket->length); + + return RD_AP_OK; +} + static char local_realm_buffer[REALM_SZ+1]; +int krb_get_lrealm(r,n) char *r; int n; @@ -470,125 +504,111 @@ krb_get_lrealm(r,n) FILE *cnffile, *fopen(); if (n > 1) - return(KFAILURE); /* Temporary restriction */ + return KFAILURE; /* Temporary restriction */ + + if (my_realm[0]) { + strcpy(r, my_realm); + return KSUCCESS; + } if (local_realm_buffer[0]) { - strcpy (r, local_realm_buffer); + strcpy(r, local_realm_buffer); return KSUCCESS; } - if ((cnffile = fopen(KRB_CONF, "r")) == NULL) { + cnffile = fopen(KRB_CONF, "r"); + if (cnffile == NULL) { if (n == 1) { - (void) strcpy(r, KRB_REALM); - return(KSUCCESS); + strcpy(r, KRB_REALM); + return KSUCCESS; + } else { + return KFAILURE; } - else - return(KFAILURE); } if (fscanf(cnffile,"%s",r) != 1) { - (void) fclose(cnffile); - return(KFAILURE); + fclose(cnffile); + return KFAILURE; } - (void) fclose(cnffile); - return(KSUCCESS); + fclose(cnffile); + return KSUCCESS; } -#endif /* KERBEROS */ +int +decomp_ticket(tkt, flags, pname, pinstance, prealm, paddress, session, + life, time_sec, sname, sinstance, key, key_s) + KTEXT tkt; /* The ticket to be decoded */ + unsigned char *flags; /* Kerberos ticket flags */ + char *pname; /* Authentication name */ + char *pinstance; /* Principal's instance */ + char *prealm; /* Principal's authentication domain */ + unsigned long *paddress; /* Net address of entity + * requesting ticket */ + C_Block session; /* Session key inserted in ticket */ + int *life; /* Lifetime of the ticket */ + unsigned long *time_sec; /* Issue time and date */ + char *sname; /* Service name */ + char *sinstance; /* Service instance */ + C_Block key; /* Service's secret key + * (to decrypt the ticket) */ + des_key_sched key_s; /* The precomputed key schedule */ +{ + static int tkt_swap_bytes; + unsigned char *uptr; + char *ptr = (char *)tkt->dat; -#ifdef ibm032 +#ifndef NOENCRYPTION + /* Do the decryption */ + pcbc_encrypt((C_Block *)tkt->dat,(C_Block *)tkt->dat, + (long) tkt->length,key_s,(C_Block *) key,0); +#endif /* ! NOENCRYPTION */ + + *flags = *ptr; /* get flags byte */ + ptr += sizeof(*flags); + tkt_swap_bytes = 0; + if (HOST_BYTE_ORDER != ((*flags >> K_FLAG_ORDER)& 1)) + tkt_swap_bytes++; + + if (strlen(ptr) > ANAME_SZ) + return(KFAILURE); + strcpy(pname,ptr); /* pname */ + ptr += strlen(pname) + 1; -#if defined (__GNUC__) || defined (__HIGHC__) -#ifdef __HIGHC__ -#define asm _ASM -#endif + if (strlen(ptr) > INST_SZ) + return(KFAILURE); + strcpy(pinstance,ptr); /* instance */ + ptr += strlen(pinstance) + 1; -/* - * Copyright (C) 1990 by the Massachusetts Institute of Technology - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted. - */ + if (strlen(ptr) > REALM_SZ) + return(KFAILURE); + strcpy(prealm,ptr); /* realm */ + ptr += strlen(prealm) + 1; + /* temporary hack until realms are dealt with properly */ + if (*prealm == 0) + strcpy(prealm, ZGetRealm()); -void asm_wrapper_kopt_c () { - /* - * Multiply routine. The C library routine tries to optimize around - * the multiply-step instruction, which was slower in earlier versions - * of the processor; this is no longer useful. Derived from assembly - * code written by John Carr. - */ - - /* data section */ - asm(".data\n.align 2"); - asm(".globl _ulmul$$ \n _ulmul$$:"); - asm(".globl _lmul$$ \n _lmul$$: .long lmul$$"); - /* text section */ - asm(".text \n .align 1"); - asm(".globl lmul$$ \n lmul$$:"); - asm(".globl ulmul$$ \n ulmul$$:"); - asm(".globl _.lmul$$ \n _.lmul$$:"); - asm(".globl _.ulmul$$ \n _.ulmul$$:"); - asm(" s r0,r0 \n mts r10,r2"); /* set up multiply, and go: */ - asm(" m r0,r3 \n m r0,r3 \n m r0,r3 \n m r0,r3"); /* execute 4 steps */ - asm(" m r0,r3 \n m r0,r3 \n m r0,r3 \n m r0,r3"); /* execute 4 steps */ - asm(" m r0,r3 \n m r0,r3 \n m r0,r3 \n m r0,r3"); /* execute 4 steps */ - asm(" m r0,r3 \n m r0,r3 \n m r0,r3 \n m r0,r3"); /* execute 4 steps */ - asm(" brx r15 \n mfs r10,r2"); /* return result */ - asm(" .long 0xdf02df00"); /* for debugging */ - -#ifdef USE_LIBC_STRLEN - } -#else - /* Note- do not use this version of strlen when compiling with -g; -g */ - /* causes extra no-ops to be inserted between instructions, which cause */ - /* the delayed branch instructions to fail. */ + memcpy((char *)paddress, ptr, 4); /* net address */ + ptr += 4; - /* - * Fast strlen, with optional trapping of null pointers. Also from - * John Carr. - */ - /* data */ - asm(".data\n.align 2"); - asm(".globl _strlen \n _strlen: .long _.strlen"); - /* text */ - asm(".text\n.align 1"); - asm(".globl _.strlen \n _.strlen:"); -#if 1 - asm(" ti 2,r2,0"); /* trap if r2 is NULL */ -#endif - asm(" ls r4,0(r2)"); - asm(" mr r0,r2"); - asm(" nilz r3,r2,3"); - asm(" beqx 0f"); - asm(" nilo r2,r2,0xfffc"); /* clear low bits */ - asm(" sis r3,2"); /* test appropriate bytes of 1st word */ - asm(" jeq 2f"); /* s & 3 == 2 */ - asm(" jm 1f"); /* s & 3 == 1 */ - asm(" j 3f"); /* s & 3 == 3 */ - asm("0: srpi16 r4,8"); /* byte 0 */ - asm(" jeq 4f"); - asm("1: niuz r5,r4,0xff"); /* byte 1 */ - asm(" jeq 5f"); - asm("2: nilz r5,r4,0xff00"); /* byte 2 */ - asm(" jeq 6f"); - asm("3: sli16 r4,8"); /* byte 3 */ - asm(" jeq 7f"); - asm(" ls r4,4(r2)"); /* get next word and continue */ - asm(" bx 0b"); - asm(" inc r2,4"); - asm("4: brx r15"); /* byte 0 is zero */ - asm(" s r2,r0"); - asm("5: s r2,r0"); /* byte 1 is zero */ - asm(" brx r15"); - asm(" inc r2,1"); - asm("6: s r2,r0"); /* byte 2 is zero */ - asm(" brx r15"); - asm(" inc r2,2"); - asm("7: s r2,r0"); /* byte 3 is zero */ - asm(" brx r15"); - asm(" inc r2,3"); - asm(" .long 0xdf02df00"); /* trace table */ + memcpy((char *)session, ptr, 8); /* session key */ + ptr+= 8; + + /* get lifetime, being certain we don't get negative lifetimes */ + uptr = (unsigned char *) ptr++; + *life = (int) *uptr; + + memcpy((char *) time_sec, ptr, 4); /* issue time */ + ptr += 4; + if (tkt_swap_bytes) + swap_u_long(*time_sec); + + strcpy(sname,ptr); /* service name */ + ptr += 1 + strlen(sname); + + strcpy(sinstance,ptr); /* instance */ + ptr += 1 + strlen(sinstance); + + return(KSUCCESS); } -#endif /* USE_LIBC_STRLEN */ -#endif /* __GNUC__ || __HIGHC__ */ -#endif /* ibm032 */ +#endif /* ZEPHYR_USES_KERBEROS */ + diff --git a/server/kopt.c.auth b/server/kopt.c.auth deleted file mode 100644 index 99fe48e..0000000 --- a/server/kopt.c.auth +++ /dev/null @@ -1,631 +0,0 @@ -/* - * $Source$ - * $Author$ - * - * Copyright 1985, 1986, 1987, 1988, 1990, 1991 by the Massachusetts - * Institute of Technology. - * - * For copying and distribution information, please see the file - * <mit-copyright.h>. - */ - -/* - * This includes code taken from: - * Kerberos: rd_req.c,v 4.16 89/03/22 14:52:06 jtkohl Exp - * Kerberos: prot.h,v 4.13 89/01/24 14:27:22 jtkohl Exp - * Kerberos: krb_conf.h,v 4.0 89/01/23 09:59:27 jtkohl Exp - */ - -#ifndef lint -#ifndef SABER -static char *rcsid_rd_req_c = - "$Id$"; -#endif /* lint */ -#endif /* SABER */ - -#ifdef KERBEROS -#ifndef NOENCRYPTION - -#include <zephyr/mit-copyright.h> -#include <zephyr/zephyr.h> -#include <stdio.h> -#include <krb.h> -#include "zserver.h" - -/* Byte ordering */ -static int krbONE = 1; -#define HOST_BYTE_ORDER (* (char *) &krbONE) - -#define KRB_PROT_VERSION 4 - -/* Message types , always leave lsb for byte order */ - -#define AUTH_MSG_KDC_REQUEST 1<<1 -#define AUTH_MSG_KDC_REPLY 2<<1 -#define AUTH_MSG_APPL_REQUEST 3<<1 -#define AUTH_MSG_APPL_REQUEST_MUTUAL 4<<1 -#define AUTH_MSG_ERR_REPLY 5<<1 -#define AUTH_MSG_PRIVATE 6<<1 -#define AUTH_MSG_SAFE 7<<1 -#define AUTH_MSG_APPL_ERR 8<<1 -#define AUTH_MSG_DIE 63<<1 - -/* values for kerb error codes */ - -#define KERB_ERR_OK 0 -#define KERB_ERR_NAME_EXP 1 -#define KERB_ERR_SERVICE_EXP 2 -#define KERB_ERR_AUTH_EXP 3 -#define KERB_ERR_PKT_VER 4 -#define KERB_ERR_NAME_MAST_KEY_VER 5 -#define KERB_ERR_SERV_MAST_KEY_VER 6 -#define KERB_ERR_BYTE_ORDER 7 -#define KERB_ERR_PRINCIPAL_UNKNOWN 8 -#define KERB_ERR_PRINCIPAL_NOT_UNIQUE 9 -#define KERB_ERR_NULL_KEY 10 - -#include <sys/time.h> -#include <string.h> - -extern int krb_ap_req_debug; - -extern struct timeval t_local; - -/* - * Keep the following information around for subsequent calls - * to this routine by the same server using the same key. - */ - -static Sched serv_ksched; /* Key sched to decrypt ticket */ -static des_cblock serv_key; /* Initialization vector */ - -static int st_kvno; /* version number for this key */ -static char st_rlm[REALM_SZ]; /* server's realm */ -static char st_nam[ANAME_SZ]; /* service name */ -static char st_inst[INST_SZ]; /* server's instance */ - -/* - * Cache of key schedules - */ -#define HASH_SIZE_1 255 /* not a power of 2 */ -#define HASH_SIZE_2 3 -static unsigned long last_use; -typedef struct { - unsigned long last_time_used; - des_cblock key; - Sched schedule; -} KeySchedRec; -static KeySchedRec scheds[HASH_SIZE_1][HASH_SIZE_2]; - -#ifdef __STDC__ -Sched* check_key_sched_cache (des_cblock key) -#else -Sched* check_key_sched_cache (key) - des_cblock key; -#endif -{ - unsigned int hash_value = key[0] + key[1] * 256; - KeySchedRec *rec = scheds[hash_value % HASH_SIZE_1]; - int i; - - for (i = HASH_SIZE_2 - 1; i >= 0; i--) - if (rec[i].last_time_used - && key[0] == rec[i].key[0] - && !memcmp (key, rec[i].key, sizeof (des_cblock))) { - rec[i].last_time_used = last_use++; - return &rec[i].schedule; - } - return 0; -} - -#ifdef __STDC__ -void add_to_key_sched_cache (des_cblock key, Sched* sched) -#else -void add_to_key_sched_cache (key, sched) - des_cblock key; - Sched* sched; -#endif -{ - unsigned int hash_value = key[0] + key[1] * 256; - KeySchedRec *rec = scheds[hash_value % HASH_SIZE_1]; - int i, oldest = HASH_SIZE_2 - 1; - - for (i = HASH_SIZE_2 - 1; i >= 0; i--) { - if (rec[i].last_time_used == 0) { - oldest = i; - break; - } - if (rec[i].last_time_used < rec[oldest].last_time_used) - oldest = i; - } - (void) memcpy (rec[oldest].key, key, sizeof (des_cblock)); - rec[oldest].schedule = *sched; - rec[oldest].last_time_used = last_use++; -} - -/* - * This file contains two functions. krb_set_key() takes a DES - * key or password string and returns a DES key (either the original - * key, or the password converted into a DES key) and a key schedule - * for it. - * - * krb_rd_req() reads an authentication request and returns information - * about the identity of the requestor, or an indication that the - * identity information was not authentic. - */ - -/* - * krb_set_key() takes as its first argument either a DES key or a - * password string. The "cvt" argument indicates how the first - * argument "key" is to be interpreted: if "cvt" is null, "key" is - * taken to be a DES key; if "cvt" is non-null, "key" is taken to - * be a password string, and is converted into a DES key using - * string_to_key(). In either case, the resulting key is returned - * in the external variable "serv_key". A key schedule is - * generated for "serv_key" and returned in the external variable - * "serv_ksched". - * - * This routine returns the return value of des_key_sched. - * - * krb_set_key() needs to be in the same .o file as krb_rd_req() so that - * the key set by krb_set_key() is available in private storage for - * krb_rd_req(). - */ - -int -krb_set_key(key,cvt) - char *key; - int cvt; -{ -#ifdef NOENCRYPTION - (void) memset(serv_key, 0, sizeof(serv_key)); - return KSUCCESS; -#else /* Encrypt */ - Sched *s; - int ret; - - if (cvt) - string_to_key(key,serv_key); - else - (void) memcpy((char *)serv_key,key,8); - - s = check_key_sched_cache (serv_key); - if (s) { - serv_ksched = *s; - return 0; - } - ret = des_key_sched (serv_key, serv_ksched.s); - add_to_key_sched_cache (serv_key, &serv_ksched); - return ret; -#endif /* NOENCRYPTION */ -} - - -/* - * krb_rd_req() takes an AUTH_MSG_APPL_REQUEST or - * AUTH_MSG_APPL_REQUEST_MUTUAL message created by krb_mk_req(), - * checks its integrity and returns a judgement as to the requestor's - * identity. - * - * The "authent" argument is a pointer to the received message. - * The "service" and "instance" arguments name the receiving server, - * and are used to get the service's ticket to decrypt the ticket - * in the message, and to compare against the server name inside the - * ticket. "from_addr" is the network address of the host from which - * the message was received; this is checked against the network - * address in the ticket. If "from_addr" is zero, the check is not - * performed. "ad" is an AUTH_DAT structure which is - * filled in with information about the sender's identity according - * to the authenticator and ticket sent in the message. Finally, - * "fn" contains the name of the file containing the server's key. - * (If "fn" is NULL, the server's key is assumed to have been set - * by krb_set_key(). If "fn" is the null string ("") the default - * file KEYFILE, defined in "krb.h", is used.) - * - * krb_rd_req() returns RD_AP_OK if the authentication information - * was genuine, or one of the following error codes (defined in - * "krb.h"): - * - * RD_AP_VERSION - wrong protocol version number - * RD_AP_MSG_TYPE - wrong message type - * RD_AP_UNDEC - couldn't decipher the message - * RD_AP_INCON - inconsistencies found - * RD_AP_BADD - wrong network address - * RD_AP_TIME - client time (in authenticator) - * too far off server time - * RD_AP_NYV - Kerberos time (in ticket) too - * far off server time - * RD_AP_EXP - ticket expired - * - * For the message format, see krb_mk_req(). - * - * Mutual authentication is not implemented. - */ - -krb_rd_req(authent,service,instance,from_addr,ad,fn) - register KTEXT authent; /* The received message */ - char *service; /* Service name */ - char *instance; /* Service instance */ - long from_addr; /* Net address of originating host */ - AUTH_DAT *ad; /* Structure to be filled in */ - char *fn; /* Filename to get keys from */ -{ - KTEXT_ST ticket; /* Temp storage for ticket */ - KTEXT tkt = &ticket; - KTEXT_ST req_id_st; /* Temp storage for authenticator */ - register KTEXT req_id = &req_id_st; - - char realm[REALM_SZ]; /* Realm of issuing kerberos */ - Sched seskey_sched, *sched; /* Key sched for session key */ - unsigned char skey[KKEY_SZ]; /* Session key from ticket */ - char sname[SNAME_SZ]; /* Service name from ticket */ - char iname[INST_SZ]; /* Instance name from ticket */ - char r_aname[ANAME_SZ]; /* Client name from authenticator */ - char r_inst[INST_SZ]; /* Client instance from authenticator */ - char r_realm[REALM_SZ]; /* Client realm from authenticator */ - unsigned int r_time_ms; /* Fine time from authenticator */ - unsigned long r_time_sec; /* Coarse time from authenticator */ - register char *ptr; /* For stepping through */ - unsigned long delta_t; /* Time in authenticator - local time */ - long tkt_age; /* Age of ticket */ - int swap_bytes; /* Need to swap bytes? */ - int mutual; /* Mutual authentication requested? */ - unsigned char s_kvno; /* Version number of the server's key - * Kerberos used to encrypt ticket */ - int status; - - if (authent->length <= 0) - return(RD_AP_MODIFIED); - - ptr = (char *) authent->dat; - - /* get msg version, type and byte order, and server key version */ - - /* check version */ - if (KRB_PROT_VERSION != (unsigned int) *ptr++) - return(RD_AP_VERSION); - - /* byte order */ - swap_bytes = 0; - if ((*ptr & 1) != HOST_BYTE_ORDER) - swap_bytes++; - - /* check msg type */ - mutual = 0; - switch (*ptr++ & ~1) { - case AUTH_MSG_APPL_REQUEST: - break; - case AUTH_MSG_APPL_REQUEST_MUTUAL: - mutual++; - break; - default: - return(RD_AP_MSG_TYPE); - } - -#ifdef lint - /* XXX mutual is set but not used; why??? */ - /* this is a crock to get lint to shut up */ - if (mutual) - mutual = 0; -#endif /* lint */ - s_kvno = *ptr++; /* get server key version */ - (void) strcpy(realm,ptr); /* And the realm of the issuing KDC */ - ptr += strlen(ptr) + 1; /* skip the realm "hint" */ - - /* - * If "fn" is NULL, key info should already be set; don't - * bother with ticket file. Otherwise, check to see if we - * already have key info for the given server and key version - * (saved in the static st_* variables). If not, go get it - * from the ticket file. If "fn" is the null string, use the - * default ticket file. - */ - if (fn && (strcmp(st_nam,service) || strcmp(st_inst,instance) || - strcmp(st_rlm,realm) || (st_kvno != s_kvno))) { - if (*fn == 0) fn = KEYFILE; - st_kvno = s_kvno; -#ifndef NOENCRYPTION - if (read_service_key(service,instance,realm,(int) s_kvno, - fn,(char *)skey)) - return(RD_AP_UNDEC); - if ((status = krb_set_key((char *)skey,0)) != 0) - return(status); -#endif /* !NOENCRYPTION */ - (void) strcpy(st_rlm,realm); - (void) strcpy(st_nam,service); - (void) strcpy(st_inst,instance); - } - - /* Get ticket from authenticator */ - tkt->length = (int) *ptr++; - if ((tkt->length + (ptr+1 - (char *) authent->dat)) > authent->length) - return(RD_AP_MODIFIED); - (void) memcpy((char *)(tkt->dat),ptr+1,tkt->length); - - if (krb_ap_req_debug) - log("ticket->length: %d",tkt->length); - -#ifndef NOENCRYPTION - /* Decrypt and take apart ticket */ -#endif - - if (decomp_ticket(tkt,&ad->k_flags,ad->pname,ad->pinst,ad->prealm, - &(ad->address),ad->session, &(ad->life), - &(ad->time_sec),sname,iname,serv_key,serv_ksched.s)) - return(RD_AP_UNDEC); - - if (krb_ap_req_debug) { - log("Ticket Contents."); - log(" Aname: %s.%s",ad->pname, - ((int)*(ad->prealm) ? ad->prealm : "Athena")); - log(" Service: %s%s%s",sname,((int)*iname ? "." : ""),iname); - } - - /* Extract the authenticator */ - req_id->length = (int) *(ptr++); - if ((req_id->length + (ptr + tkt->length - (char *) authent->dat)) > - authent->length) - return(RD_AP_MODIFIED); - (void) memcpy((char *)(req_id->dat),ptr + tkt->length, req_id->length); - -#ifndef NOENCRYPTION - /* And decrypt it with the session key from the ticket */ - if (krb_ap_req_debug) log("About to decrypt authenticator"); - sched = check_key_sched_cache (ad->session); - if (!sched) { - sched = &seskey_sched; - key_sched (ad->session, seskey_sched.s); - add_to_key_sched_cache (ad->session, &seskey_sched); - } - /* can't do much to optimize this... */ - pcbc_encrypt((C_Block *)req_id->dat,(C_Block *)req_id->dat, - (long) req_id->length, sched->s, ad->session,DES_DECRYPT); - if (krb_ap_req_debug) log("Done."); -#endif /* NOENCRYPTION */ - -#define check_ptr() if ((ptr - (char *) req_id->dat) > req_id->length) return(RD_AP_MODIFIED); - - ptr = (char *) req_id->dat; - (void) strcpy(r_aname,ptr); /* Authentication name */ - ptr += strlen(r_aname)+1; - check_ptr(); - (void) strcpy(r_inst,ptr); /* Authentication instance */ - ptr += strlen(r_inst)+1; - check_ptr(); - (void) strcpy(r_realm,ptr); /* Authentication name */ - ptr += strlen(r_realm)+1; - check_ptr(); - (void) memcpy((char *)&ad->checksum,ptr,4); /* Checksum */ - ptr += 4; - check_ptr(); - if (swap_bytes) swap_u_long(ad->checksum); - r_time_ms = *(ptr++); /* Time (fine) */ -#ifdef lint - /* XXX r_time_ms is set but not used. why??? */ - /* this is a crock to get lint to shut up */ - if (r_time_ms) - r_time_ms = 0; -#endif /* lint */ - check_ptr(); - /* assume sizeof(r_time_sec) == 4 ?? */ - (void) memcpy((char *)&r_time_sec,ptr,4); /* Time (coarse) */ - if (swap_bytes) swap_u_long(r_time_sec); - - /* Check for authenticity of the request */ - if (krb_ap_req_debug) - log("Pname: %s %s",ad->pname,r_aname); - if (strcmp(ad->pname,r_aname) != 0) - return(RD_AP_INCON); - if (strcmp(ad->pinst,r_inst) != 0) - return(RD_AP_INCON); - if (krb_ap_req_debug) - log("Realm: %s %s",ad->prealm,r_realm); - if ((strcmp(ad->prealm,r_realm) != 0)) - return(RD_AP_INCON); - - if (krb_ap_req_debug) - log("Address: %d %d",ad->address,from_addr); - if (from_addr && (ad->address != from_addr)) - return(RD_AP_BADD); - - delta_t = abs((int)(t_local.tv_sec - r_time_sec)); - if (delta_t > CLOCK_SKEW) { - (void) gettimeofday(&t_local, (struct timezone *)0); - delta_t = abs((int)(t_local.tv_sec - r_time_sec)); - if (delta_t > CLOCK_SKEW) { - if (krb_ap_req_debug) - log("Time out of range: %d - %d = %d", - t_local.tv_sec,r_time_sec,delta_t); - return(RD_AP_TIME); - } - } - - /* Now check for expiration of ticket */ - - tkt_age = t_local.tv_sec - ad->time_sec; - if (krb_ap_req_debug) - log("Time: %d Issue Date: %d Diff: %d Life %x", - t_local.tv_sec,ad->time_sec,tkt_age,ad->life); - - if (t_local.tv_sec < ad->time_sec) { - if ((ad->time_sec - t_local.tv_sec) > CLOCK_SKEW) - return(RD_AP_NYV); - } - else if ((t_local.tv_sec - ad->time_sec) > 5 * 60 * ad->life) - return(RD_AP_EXP); - - /* All seems OK */ - ad->reply.length = 0; - - return(RD_AP_OK); -} -#endif /* NOENCRYPTION */ - -int krb_find_ticket(authent, ticket) - KTEXT authent, ticket; -{ - register char *ptr; /* For stepping through */ - - /* Check for bogus length. */ - if (authent->length <= 0) - return(RD_AP_MODIFIED); - - ptr = (char *) authent->dat; - - /* check version */ - if (KRB_PROT_VERSION != (unsigned int) *ptr++) - return(RD_AP_VERSION); - - /* Make sure msg type is ok. */ - switch (*ptr++ & ~1) { - case AUTH_MSG_APPL_REQUEST: - case AUTH_MSG_APPL_REQUEST_MUTUAL: - break; - default: - return(RD_AP_MSG_TYPE); - } - - *ptr++; /* skip server key version */ - ptr += strlen(ptr) + 1; /* skip the realm "hint" */ - - /* Get ticket from authenticator */ - ticket->length = (int) *ptr++; - if ((ticket->length + (ptr+1 - (char *) authent->dat)) > authent->length) - return(RD_AP_MODIFIED); - (void) memcpy((char *)(ticket->dat),ptr+1,ticket->length); - - return RD_AP_OK; -} - -static char local_realm_buffer[REALM_SZ+1]; - -krb_get_lrealm(r,n) - char *r; - int n; -{ - FILE *cnffile, *fopen(); - - if (n > 1) - return(KFAILURE); /* Temporary restriction */ - - if (local_realm_buffer[0]) { - strcpy (r, local_realm_buffer); - return KSUCCESS; - } - - if ((cnffile = fopen(KRB_CONF, "r")) == NULL) { - if (n == 1) { - (void) strcpy(r, KRB_REALM); - return(KSUCCESS); - } - else - return(KFAILURE); - } - - if (fscanf(cnffile,"%s",r) != 1) { - (void) fclose(cnffile); - return(KFAILURE); - } - (void) fclose(cnffile); - return(KSUCCESS); -} - -#endif /* KERBEROS */ - -#ifdef ibm032 - -#if defined (__GNUC__) || defined (__HIGHC__) -#ifdef __HIGHC__ -#define asm _ASM -#endif - -/* - * Copyright (C) 1990 by the Massachusetts Institute of Technology - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted. - */ - -void asm_wrapper_kopt_c () { - /* - * Multiply routine. The C library routine tries to optimize around - * the multiply-step instruction, which was slower in earlier versions - * of the processor; this is no longer useful. Derived from assembly - * code written by John Carr. - */ - - /* data section */ - asm(".data\n.align 2"); - asm(".globl _ulmul$$ \n _ulmul$$:"); - asm(".globl _lmul$$ \n _lmul$$: .long lmul$$"); - /* text section */ - asm(".text \n .align 1"); - asm(".globl lmul$$ \n lmul$$:"); - asm(".globl ulmul$$ \n ulmul$$:"); - asm(".globl _.lmul$$ \n _.lmul$$:"); - asm(".globl _.ulmul$$ \n _.ulmul$$:"); - asm(" s r0,r0 \n mts r10,r2"); /* set up multiply, and go: */ - asm(" m r0,r3 \n m r0,r3 \n m r0,r3 \n m r0,r3"); /* execute 4 steps */ - asm(" m r0,r3 \n m r0,r3 \n m r0,r3 \n m r0,r3"); /* execute 4 steps */ - asm(" m r0,r3 \n m r0,r3 \n m r0,r3 \n m r0,r3"); /* execute 4 steps */ - asm(" m r0,r3 \n m r0,r3 \n m r0,r3 \n m r0,r3"); /* execute 4 steps */ - asm(" brx r15 \n mfs r10,r2"); /* return result */ - asm(" .long 0xdf02df00"); /* for debugging */ - -#ifdef USE_LIBC_STRLEN - } -#else - /* Note- do not use this version of strlen when compiling with -g; -g */ - /* causes extra no-ops to be inserted between instructions, which cause */ - /* the delayed branch instructions to fail. */ - - /* - * Fast strlen, with optional trapping of null pointers. Also from - * John Carr. - */ - /* data */ - asm(".data\n.align 2"); - asm(".globl _strlen \n _strlen: .long _.strlen"); - /* text */ - asm(".text\n.align 1"); - asm(".globl _.strlen \n _.strlen:"); -#if 1 - asm(" ti 2,r2,0"); /* trap if r2 is NULL */ -#endif - asm(" ls r4,0(r2)"); - asm(" mr r0,r2"); - asm(" nilz r3,r2,3"); - asm(" beqx 0f"); - asm(" nilo r2,r2,0xfffc"); /* clear low bits */ - asm(" sis r3,2"); /* test appropriate bytes of 1st word */ - asm(" jeq 2f"); /* s & 3 == 2 */ - asm(" jm 1f"); /* s & 3 == 1 */ - asm(" j 3f"); /* s & 3 == 3 */ - asm("0: srpi16 r4,8"); /* byte 0 */ - asm(" jeq 4f"); - asm("1: niuz r5,r4,0xff"); /* byte 1 */ - asm(" jeq 5f"); - asm("2: nilz r5,r4,0xff00"); /* byte 2 */ - asm(" jeq 6f"); - asm("3: sli16 r4,8"); /* byte 3 */ - asm(" jeq 7f"); - asm(" ls r4,4(r2)"); /* get next word and continue */ - asm(" bx 0b"); - asm(" inc r2,4"); - asm("4: brx r15"); /* byte 0 is zero */ - asm(" s r2,r0"); - asm("5: s r2,r0"); /* byte 1 is zero */ - asm(" brx r15"); - asm(" inc r2,1"); - asm("6: s r2,r0"); /* byte 2 is zero */ - asm(" brx r15"); - asm(" inc r2,2"); - asm("7: s r2,r0"); /* byte 3 is zero */ - asm(" brx r15"); - asm(" inc r2,3"); - asm(" .long 0xdf02df00"); /* trace table */ -} -#endif /* USE_LIBC_STRLEN */ -#endif /* __GNUC__ || __HIGHC__ */ -#endif /* ibm032 */ - diff --git a/server/kopt.c.old b/server/kopt.c.old deleted file mode 100644 index 90032f1..0000000 --- a/server/kopt.c.old +++ /dev/null @@ -1,594 +0,0 @@ -/* - * $Source$ - * $Author$ - * - * Copyright 1985, 1986, 1987, 1988, 1990, 1991 by the Massachusetts - * Institute of Technology. - * - * For copying and distribution information, please see the file - * <mit-copyright.h>. - */ - -/* - * This includes code taken from: - * Kerberos: rd_req.c,v 4.16 89/03/22 14:52:06 jtkohl Exp - * Kerberos: prot.h,v 4.13 89/01/24 14:27:22 jtkohl Exp - * Kerberos: krb_conf.h,v 4.0 89/01/23 09:59:27 jtkohl Exp - */ - -#ifndef lint -#ifndef SABER -static char *rcsid_rd_req_c = - "$Id$"; -#endif /* lint */ -#endif /* SABER */ - -#ifdef KERBEROS -#ifndef NOENCRYPTION - -#include <zephyr/mit-copyright.h> -#include <zephyr/zephyr.h> -#include <stdio.h> -#include <krb.h> -#include "zserver.h" - -/* Byte ordering */ -extern int krbONE; -#define HOST_BYTE_ORDER (* (char *) &krbONE) - -#define KRB_PROT_VERSION 4 - -/* Message types , always leave lsb for byte order */ - -#define AUTH_MSG_KDC_REQUEST 1<<1 -#define AUTH_MSG_KDC_REPLY 2<<1 -#define AUTH_MSG_APPL_REQUEST 3<<1 -#define AUTH_MSG_APPL_REQUEST_MUTUAL 4<<1 -#define AUTH_MSG_ERR_REPLY 5<<1 -#define AUTH_MSG_PRIVATE 6<<1 -#define AUTH_MSG_SAFE 7<<1 -#define AUTH_MSG_APPL_ERR 8<<1 -#define AUTH_MSG_DIE 63<<1 - -/* values for kerb error codes */ - -#define KERB_ERR_OK 0 -#define KERB_ERR_NAME_EXP 1 -#define KERB_ERR_SERVICE_EXP 2 -#define KERB_ERR_AUTH_EXP 3 -#define KERB_ERR_PKT_VER 4 -#define KERB_ERR_NAME_MAST_KEY_VER 5 -#define KERB_ERR_SERV_MAST_KEY_VER 6 -#define KERB_ERR_BYTE_ORDER 7 -#define KERB_ERR_PRINCIPAL_UNKNOWN 8 -#define KERB_ERR_PRINCIPAL_NOT_UNIQUE 9 -#define KERB_ERR_NULL_KEY 10 - -#include <sys/time.h> -#include <strings.h> - -extern int krb_ap_req_debug; - -extern struct timeval t_local; - -/* - * Keep the following information around for subsequent calls - * to this routine by the same server using the same key. - */ - -static Sched serv_ksched; /* Key sched to decrypt ticket */ -static des_cblock serv_key; /* Initialization vector */ - -static int st_kvno; /* version number for this key */ -static char st_rlm[REALM_SZ]; /* server's realm */ -static char st_nam[ANAME_SZ]; /* service name */ -static char st_inst[INST_SZ]; /* server's instance */ - -/* - * Cache of key schedules - */ -#define HASH_SIZE_1 255 /* not a power of 2 */ -#define HASH_SIZE_2 3 -static unsigned long last_use; -typedef struct { - unsigned long last_time_used; - des_cblock key; - Sched schedule; -} KeySchedRec; -static KeySchedRec scheds[HASH_SIZE_1][HASH_SIZE_2]; - -#ifdef __STDC__ -Sched* check_key_sched_cache (des_cblock key) -#else -Sched* check_key_sched_cache (key) - des_cblock key; -#endif -{ - unsigned int hash_value = key[0] + key[1] * 256; - KeySchedRec *rec = scheds[hash_value % HASH_SIZE_1]; - int i; - - for (i = HASH_SIZE_2 - 1; i >= 0; i--) - if (rec[i].last_time_used - && key[0] == rec[i].key[0] - && !memcmp (key, rec[i].key, sizeof (des_cblock))) { - rec[i].last_time_used = last_use++; - return &rec[i].schedule; - } - return 0; -} - -#ifdef __STDC__ -void add_to_key_sched_cache (des_cblock key, Sched* sched) -#else -void add_to_key_sched_cache (key, sched) - des_cblock key; - Sched* sched; -#endif -{ - unsigned int hash_value = key[0] + key[1] * 256; - KeySchedRec *rec = scheds[hash_value % HASH_SIZE_1]; - int i, oldest = HASH_SIZE_2 - 1; - - for (i = HASH_SIZE_2 - 1; i >= 0; i--) { - if (rec[i].last_time_used == 0) { - oldest = i; - break; - } - if (rec[i].last_time_used < rec[oldest].last_time_used) - oldest = i; - } - (void) memcpy (rec[oldest].key, key, sizeof (des_cblock)); - rec[oldest].schedule = *sched; - rec[oldest].last_time_used = last_use++; -} - -/* - * This file contains two functions. krb_set_key() takes a DES - * key or password string and returns a DES key (either the original - * key, or the password converted into a DES key) and a key schedule - * for it. - * - * krb_rd_req() reads an authentication request and returns information - * about the identity of the requestor, or an indication that the - * identity information was not authentic. - */ - -/* - * krb_set_key() takes as its first argument either a DES key or a - * password string. The "cvt" argument indicates how the first - * argument "key" is to be interpreted: if "cvt" is null, "key" is - * taken to be a DES key; if "cvt" is non-null, "key" is taken to - * be a password string, and is converted into a DES key using - * string_to_key(). In either case, the resulting key is returned - * in the external variable "serv_key". A key schedule is - * generated for "serv_key" and returned in the external variable - * "serv_ksched". - * - * This routine returns the return value of des_key_sched. - * - * krb_set_key() needs to be in the same .o file as krb_rd_req() so that - * the key set by krb_set_key() is available in private storage for - * krb_rd_req(). - */ - -int -krb_set_key(key,cvt) - char *key; - int cvt; -{ -#ifdef NOENCRYPTION - (void) memset(serv_key, 0, sizeof(serv_key)); - return KSUCCESS; -#else /* Encrypt */ - Sched *s; - int ret; - - if (cvt) - string_to_key(key,serv_key); - else - (void) memcpy((char *)serv_key,key,8); - - s = check_key_sched_cache (serv_key); - if (s) { - serv_ksched = *s; - return 0; - } - ret = des_key_sched (serv_key, serv_ksched.s); - add_to_key_sched_cache (serv_key, &serv_ksched); - return ret; -#endif /* NOENCRYPTION */ -} - - -/* - * krb_rd_req() takes an AUTH_MSG_APPL_REQUEST or - * AUTH_MSG_APPL_REQUEST_MUTUAL message created by krb_mk_req(), - * checks its integrity and returns a judgement as to the requestor's - * identity. - * - * The "authent" argument is a pointer to the received message. - * The "service" and "instance" arguments name the receiving server, - * and are used to get the service's ticket to decrypt the ticket - * in the message, and to compare against the server name inside the - * ticket. "from_addr" is the network address of the host from which - * the message was received; this is checked against the network - * address in the ticket. If "from_addr" is zero, the check is not - * performed. "ad" is an AUTH_DAT structure which is - * filled in with information about the sender's identity according - * to the authenticator and ticket sent in the message. Finally, - * "fn" contains the name of the file containing the server's key. - * (If "fn" is NULL, the server's key is assumed to have been set - * by krb_set_key(). If "fn" is the null string ("") the default - * file KEYFILE, defined in "krb.h", is used.) - * - * krb_rd_req() returns RD_AP_OK if the authentication information - * was genuine, or one of the following error codes (defined in - * "krb.h"): - * - * RD_AP_VERSION - wrong protocol version number - * RD_AP_MSG_TYPE - wrong message type - * RD_AP_UNDEC - couldn't decipher the message - * RD_AP_INCON - inconsistencies found - * RD_AP_BADD - wrong network address - * RD_AP_TIME - client time (in authenticator) - * too far off server time - * RD_AP_NYV - Kerberos time (in ticket) too - * far off server time - * RD_AP_EXP - ticket expired - * - * For the message format, see krb_mk_req(). - * - * Mutual authentication is not implemented. - */ - -krb_rd_req(authent,service,instance,from_addr,ad,fn) - register KTEXT authent; /* The received message */ - char *service; /* Service name */ - char *instance; /* Service instance */ - long from_addr; /* Net address of originating host */ - AUTH_DAT *ad; /* Structure to be filled in */ - char *fn; /* Filename to get keys from */ -{ - KTEXT_ST ticket; /* Temp storage for ticket */ - KTEXT tkt = &ticket; - KTEXT_ST req_id_st; /* Temp storage for authenticator */ - register KTEXT req_id = &req_id_st; - - char realm[REALM_SZ]; /* Realm of issuing kerberos */ - Sched seskey_sched, *sched; /* Key sched for session key */ - unsigned char skey[KKEY_SZ]; /* Session key from ticket */ - char sname[SNAME_SZ]; /* Service name from ticket */ - char iname[INST_SZ]; /* Instance name from ticket */ - char r_aname[ANAME_SZ]; /* Client name from authenticator */ - char r_inst[INST_SZ]; /* Client instance from authenticator */ - char r_realm[REALM_SZ]; /* Client realm from authenticator */ - unsigned int r_time_ms; /* Fine time from authenticator */ - unsigned long r_time_sec; /* Coarse time from authenticator */ - register char *ptr; /* For stepping through */ - unsigned long delta_t; /* Time in authenticator - local time */ - long tkt_age; /* Age of ticket */ - int swap_bytes; /* Need to swap bytes? */ - int mutual; /* Mutual authentication requested? */ - unsigned char s_kvno; /* Version number of the server's key - * Kerberos used to encrypt ticket */ - int status; - - if (authent->length <= 0) - return(RD_AP_MODIFIED); - - ptr = (char *) authent->dat; - - /* get msg version, type and byte order, and server key version */ - - /* check version */ - if (KRB_PROT_VERSION != (unsigned int) *ptr++) - return(RD_AP_VERSION); - - /* byte order */ - swap_bytes = 0; - if ((*ptr & 1) != HOST_BYTE_ORDER) - swap_bytes++; - - /* check msg type */ - mutual = 0; - switch (*ptr++ & ~1) { - case AUTH_MSG_APPL_REQUEST: - break; - case AUTH_MSG_APPL_REQUEST_MUTUAL: - mutual++; - break; - default: - return(RD_AP_MSG_TYPE); - } - -#ifdef lint - /* XXX mutual is set but not used; why??? */ - /* this is a crock to get lint to shut up */ - if (mutual) - mutual = 0; -#endif /* lint */ - s_kvno = *ptr++; /* get server key version */ - (void) strcpy(realm,ptr); /* And the realm of the issuing KDC */ - ptr += strlen(ptr) + 1; /* skip the realm "hint" */ - - /* - * If "fn" is NULL, key info should already be set; don't - * bother with ticket file. Otherwise, check to see if we - * already have key info for the given server and key version - * (saved in the static st_* variables). If not, go get it - * from the ticket file. If "fn" is the null string, use the - * default ticket file. - */ - if (fn && (strcmp(st_nam,service) || strcmp(st_inst,instance) || - strcmp(st_rlm,realm) || (st_kvno != s_kvno))) { - if (*fn == 0) fn = KEYFILE; - st_kvno = s_kvno; -#ifndef NOENCRYPTION - if (read_service_key(service,instance,realm,(int) s_kvno, - fn,(char *)skey)) - return(RD_AP_UNDEC); - if ((status = krb_set_key((char *)skey,0)) != 0) - return(status); -#endif /* !NOENCRYPTION */ - (void) strcpy(st_rlm,realm); - (void) strcpy(st_nam,service); - (void) strcpy(st_inst,instance); - } - - /* Get ticket from authenticator */ - tkt->length = (int) *ptr++; - if ((tkt->length + (ptr+1 - (char *) authent->dat)) > authent->length) - return(RD_AP_MODIFIED); - (void) memcpy((char *)(tkt->dat),ptr+1,tkt->length); - - if (krb_ap_req_debug) - log("ticket->length: %d",tkt->length); - -#ifndef NOENCRYPTION - /* Decrypt and take apart ticket */ -#endif - - if (decomp_ticket(tkt,&ad->k_flags,ad->pname,ad->pinst,ad->prealm, - &(ad->address),ad->session, &(ad->life), - &(ad->time_sec),sname,iname,serv_key,serv_ksched.s)) - return(RD_AP_UNDEC); - - if (krb_ap_req_debug) { - log("Ticket Contents."); - log(" Aname: %s.%s",ad->pname, - ((int)*(ad->prealm) ? ad->prealm : "Athena")); - log(" Service: %s%s%s",sname,((int)*iname ? "." : ""),iname); - } - - /* Extract the authenticator */ - req_id->length = (int) *(ptr++); - if ((req_id->length + (ptr + tkt->length - (char *) authent->dat)) > - authent->length) - return(RD_AP_MODIFIED); - (void) memcpy((char *)(req_id->dat),ptr + tkt->length, req_id->length); - -#ifndef NOENCRYPTION - /* And decrypt it with the session key from the ticket */ - if (krb_ap_req_debug) log("About to decrypt authenticator"); - sched = check_key_sched_cache (ad->session); - if (!sched) { - sched = &seskey_sched; - key_sched (ad->session, seskey_sched.s); - add_to_key_sched_cache (ad->session, &seskey_sched); - } - /* can't do much to optimize this... */ - pcbc_encrypt((C_Block *)req_id->dat,(C_Block *)req_id->dat, - (long) req_id->length, sched->s, ad->session,DES_DECRYPT); - if (krb_ap_req_debug) log("Done."); -#endif /* NOENCRYPTION */ - -#define check_ptr() if ((ptr - (char *) req_id->dat) > req_id->length) return(RD_AP_MODIFIED); - - ptr = (char *) req_id->dat; - (void) strcpy(r_aname,ptr); /* Authentication name */ - ptr += strlen(r_aname)+1; - check_ptr(); - (void) strcpy(r_inst,ptr); /* Authentication instance */ - ptr += strlen(r_inst)+1; - check_ptr(); - (void) strcpy(r_realm,ptr); /* Authentication name */ - ptr += strlen(r_realm)+1; - check_ptr(); - (void) memcpy((char *)&ad->checksum,ptr,4); /* Checksum */ - ptr += 4; - check_ptr(); - if (swap_bytes) swap_u_long(ad->checksum); - r_time_ms = *(ptr++); /* Time (fine) */ -#ifdef lint - /* XXX r_time_ms is set but not used. why??? */ - /* this is a crock to get lint to shut up */ - if (r_time_ms) - r_time_ms = 0; -#endif /* lint */ - check_ptr(); - /* assume sizeof(r_time_sec) == 4 ?? */ - (void) memcpy((char *)&r_time_sec,ptr,4); /* Time (coarse) */ - if (swap_bytes) swap_u_long(r_time_sec); - - /* Check for authenticity of the request */ - if (krb_ap_req_debug) - log("Pname: %s %s",ad->pname,r_aname); - if (strcmp(ad->pname,r_aname) != 0) - return(RD_AP_INCON); - if (strcmp(ad->pinst,r_inst) != 0) - return(RD_AP_INCON); - if (krb_ap_req_debug) - log("Realm: %s %s",ad->prealm,r_realm); - if ((strcmp(ad->prealm,r_realm) != 0)) - return(RD_AP_INCON); - - if (krb_ap_req_debug) - log("Address: %d %d",ad->address,from_addr); - if (from_addr && (ad->address != from_addr)) - return(RD_AP_BADD); - - delta_t = abs((int)(t_local.tv_sec - r_time_sec)); - if (delta_t > CLOCK_SKEW) { - (void) gettimeofday(&t_local, (struct timezone *)0); - delta_t = abs((int)(t_local.tv_sec - r_time_sec)); - if (delta_t > CLOCK_SKEW) { - if (krb_ap_req_debug) - log("Time out of range: %d - %d = %d", - t_local.tv_sec,r_time_sec,delta_t); - return(RD_AP_TIME); - } - } - - /* Now check for expiration of ticket */ - - tkt_age = t_local.tv_sec - ad->time_sec; - if (krb_ap_req_debug) - log("Time: %d Issue Date: %d Diff: %d Life %x", - t_local.tv_sec,ad->time_sec,tkt_age,ad->life); - - if (t_local.tv_sec < ad->time_sec) { - if ((ad->time_sec - t_local.tv_sec) > CLOCK_SKEW) - return(RD_AP_NYV); - } - else if ((t_local.tv_sec - ad->time_sec) > 5 * 60 * ad->life) - return(RD_AP_EXP); - - /* All seems OK */ - ad->reply.length = 0; - - return(RD_AP_OK); -} -#endif /* NOENCRYPTION */ - -static char local_realm_buffer[REALM_SZ+1]; - -krb_get_lrealm(r,n) - char *r; - int n; -{ - FILE *cnffile, *fopen(); - - if (n > 1) - return(KFAILURE); /* Temporary restriction */ - - if (local_realm_buffer[0]) { - strcpy (r, local_realm_buffer); - return KSUCCESS; - } - - if ((cnffile = fopen(KRB_CONF, "r")) == NULL) { - if (n == 1) { - (void) strcpy(r, KRB_REALM); - return(KSUCCESS); - } - else - return(KFAILURE); - } - - if (fscanf(cnffile,"%s",r) != 1) { - (void) fclose(cnffile); - return(KFAILURE); - } - (void) fclose(cnffile); - return(KSUCCESS); -} - -#endif /* KERBEROS */ - -#ifdef ibm032 - -#if defined (__GNUC__) || defined (__HIGHC__) -#ifdef __HIGHC__ -#define asm _ASM -#endif - -/* - * Copyright (C) 1990 by the Massachusetts Institute of Technology - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted. - */ - -void asm_wrapper_kopt_c () { - /* - * Multiply routine. The C library routine tries to optimize around - * the multiply-step instruction, which was slower in earlier versions - * of the processor; this is no longer useful. Derived from assembly - * code written by John Carr. - */ - - /* data section */ - asm(".data\n.align 2"); - asm(".globl _ulmul$$ \n _ulmul$$:"); - asm(".globl _lmul$$ \n _lmul$$: .long lmul$$"); - /* text section */ - asm(".text \n .align 1"); - asm(".globl lmul$$ \n lmul$$:"); - asm(".globl ulmul$$ \n ulmul$$:"); - asm(".globl _.lmul$$ \n _.lmul$$:"); - asm(".globl _.ulmul$$ \n _.ulmul$$:"); - asm(" s r0,r0 \n mts r10,r2"); /* set up multiply, and go: */ - asm(" m r0,r3 \n m r0,r3 \n m r0,r3 \n m r0,r3"); /* execute 4 steps */ - asm(" m r0,r3 \n m r0,r3 \n m r0,r3 \n m r0,r3"); /* execute 4 steps */ - asm(" m r0,r3 \n m r0,r3 \n m r0,r3 \n m r0,r3"); /* execute 4 steps */ - asm(" m r0,r3 \n m r0,r3 \n m r0,r3 \n m r0,r3"); /* execute 4 steps */ - asm(" brx r15 \n mfs r10,r2"); /* return result */ - asm(" .long 0xdf02df00"); /* for debugging */ - -#ifdef USE_LIBC_STRLEN - } -#else - /* Note- do not use this version of strlen when compiling with -g; -g */ - /* causes extra no-ops to be inserted between instructions, which cause */ - /* the delayed branch instructions to fail. */ - - /* - * Fast strlen, with optional trapping of null pointers. Also from - * John Carr. - */ - /* data */ - asm(".data\n.align 2"); - asm(".globl _strlen \n _strlen: .long _.strlen"); - /* text */ - asm(".text\n.align 1"); - asm(".globl _.strlen \n _.strlen:"); -#if 1 - asm(" ti 2,r2,0"); /* trap if r2 is NULL */ -#endif - asm(" ls r4,0(r2)"); - asm(" mr r0,r2"); - asm(" nilz r3,r2,3"); - asm(" beqx 0f"); - asm(" nilo r2,r2,0xfffc"); /* clear low bits */ - asm(" sis r3,2"); /* test appropriate bytes of 1st word */ - asm(" jeq 2f"); /* s & 3 == 2 */ - asm(" jm 1f"); /* s & 3 == 1 */ - asm(" j 3f"); /* s & 3 == 3 */ - asm("0: srpi16 r4,8"); /* byte 0 */ - asm(" jeq 4f"); - asm("1: niuz r5,r4,0xff"); /* byte 1 */ - asm(" jeq 5f"); - asm("2: nilz r5,r4,0xff00"); /* byte 2 */ - asm(" jeq 6f"); - asm("3: sli16 r4,8"); /* byte 3 */ - asm(" jeq 7f"); - asm(" ls r4,4(r2)"); /* get next word and continue */ - asm(" bx 0b"); - asm(" inc r2,4"); - asm("4: brx r15"); /* byte 0 is zero */ - asm(" s r2,r0"); - asm("5: s r2,r0"); /* byte 1 is zero */ - asm(" brx r15"); - asm(" inc r2,1"); - asm("6: s r2,r0"); /* byte 2 is zero */ - asm(" brx r15"); - asm(" inc r2,2"); - asm("7: s r2,r0"); /* byte 3 is zero */ - asm(" brx r15"); - asm(" inc r2,3"); - asm(" .long 0xdf02df00"); /* trace table */ -} -#endif /* USE_LIBC_STRLEN */ -#endif /* __GNUC__ || __HIGHC__ */ -#endif /* ibm032 */ diff --git a/server/kstuff.c b/server/kstuff.c index 49089de..ff695f5 100644 --- a/server/kstuff.c +++ b/server/kstuff.c @@ -1,4 +1,3 @@ -#ifdef KERBEROS /* This file is part of the Project Athena Zephyr Notification System. * It contains functions for dealing with Kerberos functions in the server. * @@ -13,40 +12,42 @@ * $Header$ */ +#include "zserver.h" + #ifndef lint #ifndef SABER -static char rcsid_kstuff_c[] = "$Id$"; +static const char rcsid_kstuff_c[] = "$Id$"; #endif #endif -#include "zserver.h" +#ifdef ZEPHYR_USES_KERBEROS -#include <ctype.h> -#include <netdb.h> -#include <string.h> +/* Keep a hash table mapping tickets to session keys, so we can do a fast + * check of the cryptographic checksum without doing and DES decryptions. + * Also remember the expiry time of the ticket, so that we can sweep the + * table periodically. */ -#include <zephyr/zephyr_internal.h> -#ifdef KERBEROS -#include <zephyr/krb_err.h> -#endif +#define HASHTAB_SIZE 4091 -static char tkt_file[] = ZEPHYR_TKFILE; +typedef struct hash_entry Hash_entry; - -struct AuthEnt { - Zconst char *data; - int len; - ZSTRING *principal; -#ifndef NOENCRYPTION +/* The ticket comes at the end, in a variable-length array. */ +struct hash_entry { C_Block session_key; -#endif - long expire_time; - struct sockaddr_in from; + time_t expires; + char srcprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4]; + Hash_entry *next; + int ticket_len; + unsigned char ticket[1]; }; -#define HASH_SIZE_1 513 -#define HASH_SIZE_2 3 -static struct AuthEnt auth_cache[HASH_SIZE_1][HASH_SIZE_2]; +Hash_entry *hashtab[HASHTAB_SIZE]; + +static int hash_ticket __P((unsigned char *, int)); +static void add_session_key __P((KTEXT, C_Block, char *, time_t)); +static int find_session_key __P((KTEXT, C_Block, char *)); +static ZChecksum_t compute_checksum __P((ZNotice_t *, C_Block)); +static ZChecksum_t compute_rlm_checksum __P((ZNotice_t *, C_Block)); /* * GetKerberosData @@ -114,7 +115,7 @@ GetKerberosData(fd, haddr, kdata, service, srvtab) int SendKerberosData(fd, ticket, service, host) - int fd; /* file descriptor to write onto */ + int fd; /* file descriptor to write onto */ KTEXT ticket; /* where to put ticket (return) */ char *service; /* service name, foreign host */ char *host; @@ -125,242 +126,327 @@ SendKerberosData(fd, ticket, service, host) int written; int size_to_write; - rem = krb_get_lrealm(krb_realm,1); - if (rem != KSUCCESS) - return rem + krb_err_base; - - rem = krb_mk_req( ticket, service, host, krb_realm, (u_long)0 ); + rem = krb_mk_req(ticket, service, host, ZGetRealm(), (u_long) 0); if (rem != KSUCCESS) return rem + krb_err_base; (void) sprintf(p,"%d ",ticket->length); size_to_write = strlen (p); if ((written = write(fd, p, size_to_write)) != size_to_write) - if (written < 0) - return errno; - else - return ZSRV_PKSHORT; - if ((written = write(fd, (caddr_t) (ticket->dat), ticket->length)) != ticket->length) - if (written < 0) - return errno; - else - return ZSRV_PKSHORT; + return (written < 0) ? errno : ZSRV_PKSHORT; + if ((written = write(fd, (caddr_t) (ticket->dat), ticket->length)) + != ticket->length) + return (written < 0) ? errno : ZSRV_PKSHORT; return 0; } -/* Hack to replace the kerberos library's idea of the ticket file with - our idea */ -char * -tkt_string() -{ - return tkt_file; -} +#endif /* ZEPHYR_USES_KERBEROS */ -/* Check authentication of the notice. - If it looks authentic but fails the Kerberos check, return -1. - If it looks authentic and passes the Kerberos check, return 1. - If it doesn't look authentic, return 0 - - When not using Kerberos, return (looks-authentic-p) - */ +int +ZCheckRealmAuthentication(notice, from, realm) + ZNotice_t *notice; + struct sockaddr_in *from; + char *realm; +{ +#ifdef ZEPHYR_USES_KERBEROS + int result; + char rlmprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4]; + char srcprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4]; + KTEXT_ST authent, ticket; + AUTH_DAT dat; + ZChecksum_t checksum; + CREDENTIALS cred; + C_Block session_key; -static void -ae_expire(ae) - struct AuthEnt *ae; -{ - if (ae->data) { - xfree((void *) ae->data); - ae->data = 0; - } - ae->len = 0; - ae->expire_time = 0; - free_zstring(ae->principal); - ae->principal= 0; -} + if (!notice->z_auth) + return ZAUTH_NO; -static int -auth_hash (str, len) - Zconst char *str; - int len; -{ - unsigned long hash; - if (len <= 3) - return str[0]; - hash = str[len - 1] * 256 + str[len-2] * 16 + str[len-3]; - hash %= HASH_SIZE_1; - return hash; -} + /* Check for bogus authentication data length. */ + if (notice->z_authent_len <= 0) + return ZAUTH_FAILED; -static int -check_cache (notice, from) - ZNotice_t *notice; - struct sockaddr_in *from; - { - Zconst char *str = notice->z_ascii_authent; - int len, i; - unsigned int hash_val = 0; - unsigned long now = time(0); - struct AuthEnt *a; - - len = strlen (str); - hash_val = auth_hash (str, len); - for (i = 0; i < HASH_SIZE_2; i++) { - a = &auth_cache[hash_val][i]; - if (!a->data) { - continue; - } - if (now > a->expire_time) { - ae_expire(a); - continue; - } - if (len != a->len) { - continue; - } - if (strcmp (notice->z_ascii_authent, a->data)) { - continue; - } - /* Okay, we know we've got the same authenticator. */ - if (strcmp (notice->z_sender, a->principal->string)) { - return ZAUTH_FAILED; - } - if (from->sin_addr.s_addr != a->from.sin_addr.s_addr) { - return ZAUTH_FAILED; - } -#ifndef NOENCRYPTION - (void) memcpy (__Zephyr_session, a->session_key, sizeof (C_Block)); -#endif - return ZAUTH_YES; + /* Read in the authentication data. */ + if (ZReadAscii(notice->z_ascii_authent, + strlen(notice->z_ascii_authent)+1, + (unsigned char *)authent.dat, + notice->z_authent_len) == ZERR_BADFIELD) { + return ZAUTH_FAILED; + } + authent.length = notice->z_authent_len; + + /* Copy the ticket out of the authentication data. */ + if (krb_find_ticket(&authent, &ticket) != RD_AP_OK) + return ZAUTH_FAILED; + + (void) sprintf(rlmprincipal, "%s.%s@%s", SERVER_SERVICE, + SERVER_INSTANCE, realm); + + /* Try to do a fast check against the cryptographic checksum. */ + if (find_session_key(&ticket, session_key, srcprincipal) >= 0) { + if (strcmp(srcprincipal, rlmprincipal) != 0) + return ZAUTH_FAILED; + if (notice->z_time.tv_sec - NOW > CLOCK_SKEW) + return ZAUTH_FAILED; + checksum = compute_rlm_checksum(notice, session_key); + + /* If checksum matches, packet is authentic. Otherwise, check + * the authenticator as if we didn't have the session key cached + * and return ZAUTH_CKSUM_FAILED. This is a rare case (since the + * ticket isn't cached after a checksum failure), so don't worry + * about the extra des_quad_cksum() call. */ + if (checksum == notice->z_checksum) { + memcpy(__Zephyr_session, session_key, sizeof(C_Block)); + return ZAUTH_YES; + } } - return ZAUTH_NO; -} -void -add_to_cache (a) - struct AuthEnt *a; -{ - int len, i, j; - struct AuthEnt *entries; - unsigned int hash_val = 0; - - len = a->len; - hash_val = auth_hash (a->data, len); - entries = auth_cache[hash_val]; - j = 0; - for (i = 0; i < HASH_SIZE_2; i++) { - if (entries[i].data == 0) { - j = i; - goto ok; - } - if (i == j) - continue; - if (entries[i].expire_time < entries[j].expire_time) - j = i; + /* We don't have the session key cached; do it the long way. */ + result = krb_rd_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, + from->sin_addr.s_addr, &dat, srvtab_file); + if (result == RD_AP_OK) { + sprintf(srcprincipal, "%s%s%s@%s", dat.pname, dat.pinst[0] ? "." : "", + dat.pinst, dat.prealm); + if (strcmp(rlmprincipal, srcprincipal)) + return ZAUTH_FAILED; + } else { + return ZAUTH_FAILED; /* didn't decode correctly */ } -ok: - if (entries[j].data) - ae_expire(&entries[j]); - entries[j] = *a; + + /* Check the cryptographic checksum. */ +#ifdef NOENCRYPTION + our_checksum = 0; +#else + checksum = compute_rlm_checksum(notice, dat.session); +#endif + if (checksum != notice->z_checksum) + return ZAUTH_CKSUM_FAILED; + + /* Record the session key, expiry time, and source principal in the + * hash table, so we can do a fast check next time. */ + add_session_key(&ticket, dat.session, srcprincipal, + (time_t)(dat.time_sec + dat.life * 5 * 60)); + + return ZAUTH_YES; + +#else /* !ZEPHYR_USES_KERBEROS */ + return (notice->z_auth) ? ZAUTH_YES : ZAUTH_NO; +#endif } int ZCheckAuthentication(notice, from) - ZNotice_t *notice; - struct sockaddr_in *from; + ZNotice_t *notice; + struct sockaddr_in *from; { +#ifdef ZEPHYR_USES_KERBEROS int result; char srcprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4]; - KTEXT_ST authent; + KTEXT_ST authent, ticket; AUTH_DAT dat; - ZChecksum_t our_checksum; - CREDENTIALS cred; - struct AuthEnt a; - char *s; - int auth_len = 0; + ZChecksum_t checksum; + C_Block session_key; + + if (!notice->z_auth) + return ZAUTH_NO; + /* Check for bogus authentication data length. */ + if (notice->z_authent_len <= 0) + return ZAUTH_FAILED; - if (!notice->z_auth) { - return (ZAUTH_NO); + /* Read in the authentication data. */ + if (ZReadAscii(notice->z_ascii_authent, + strlen(notice->z_ascii_authent)+1, + (unsigned char *)authent.dat, + notice->z_authent_len) == ZERR_BADFIELD) { + return ZAUTH_FAILED; } + authent.length = notice->z_authent_len; - if (__Zephyr_server) { - - if (notice->z_authent_len <= 0) { /* bogus length */ -#if 0 - syslog (LOG_DEBUG, "z_authent_len = %d -> AUTH_FAILED", - notice->z_authent_len); -#endif - return(ZAUTH_FAILED); - } + /* Copy the ticket out of the authentication data. */ + if (krb_find_ticket(&authent, &ticket) != RD_AP_OK) + return ZAUTH_FAILED; - auth_len = strlen (notice->z_ascii_authent); - if (ZReadAscii(notice->z_ascii_authent, auth_len + 1, - (unsigned char *)authent.dat, - notice->z_authent_len) == ZERR_BADFIELD) { - syslog (LOG_DEBUG, - "ZReadAscii failed (len:%s) -> AUTH_FAILED (from %s)", - error_message (ZERR_BADFIELD), inet_ntoa (from->sin_addr)); - return (ZAUTH_FAILED); - } - authent.length = notice->z_authent_len; - result = check_cache (notice, from); - if (result != ZAUTH_NO) - return result; - - /* Well, it's not in the cache... decode it. */ - result = krb_rd_req(&authent, SERVER_SERVICE, - SERVER_INSTANCE, (int) from->sin_addr.s_addr, - &dat, SERVER_SRVTAB); - if (result == RD_AP_OK) { - (void) memcpy ((void *) a.session_key,(void *) dat.session, - sizeof(C_Block)); - (void) memcpy((char *)__Zephyr_session, (char *)dat.session, - sizeof(C_Block)); - (void) sprintf(srcprincipal, "%s%s%s@%s", dat.pname, - dat.pinst[0]?".":"", dat.pinst, dat.prealm); - if (strcmp(srcprincipal, notice->z_sender)) { - syslog (LOG_DEBUG, "principal mismatch->AUTH_FAILED"); - return (ZAUTH_FAILED); - } - a.principal = make_zstring(srcprincipal,0); - a.expire_time = time (0) + 5 * 60; /* add 5 minutes */ - a.from = *from; - s = (char *) xmalloc (auth_len + 1); - strcpy (s, notice->z_ascii_authent); - a.data = s; - a.len = auth_len; - add_to_cache (&a); - return(ZAUTH_YES); - } else { - syslog (LOG_DEBUG, "krb_rd_req failed (%s)->AUTH_FAILED (from %s)", - krb_err_txt [result], inet_ntoa (from->sin_addr)); - return (ZAUTH_FAILED); /* didn't decode correctly */ + /* Try to do a fast check against the cryptographic checksum. */ + if (find_session_key(&ticket, session_key, srcprincipal) >= 0) { + if (strcmp(srcprincipal, notice->z_sender) != 0) + return ZAUTH_FAILED; + if (notice->z_time.tv_sec - NOW > CLOCK_SKEW) + return ZAUTH_FAILED; + checksum = compute_checksum(notice, session_key); + + /* If the checksum matches, the packet is authentic. Otherwise, + * check authenticator as if we didn't have the session key cached + * and return ZAUTH_CKSUM_FAILED. This is a rare case (since the + * ticket isn't cached after a checksum failure), so don't worry + * about the extra des_quad_cksum() call. */ + if (checksum == notice->z_checksum) { + memcpy(__Zephyr_session, session_key, sizeof(C_Block)); + return ZAUTH_YES; } } - - if ((result = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, - __Zephyr_realm, &cred)) != KSUCCESS) { - syslog (LOG_DEBUG, "krb_get_cred failed (%s) ->AUTH_NO (from %s)", - krb_err_txt [result], inet_ntoa (from->sin_addr)); - return (ZAUTH_NO); + + /* We don't have the session key cached; do it the long way. */ + result = krb_rd_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, + from->sin_addr.s_addr, &dat, srvtab_file); + if (result == RD_AP_OK) { + memcpy(__Zephyr_session, dat.session, sizeof(C_Block)); + sprintf(srcprincipal, "%s%s%s@%s", dat.pname, dat.pinst[0] ? "." : "", + dat.pinst, dat.prealm); + if (strcmp(srcprincipal, notice->z_sender)) + return ZAUTH_FAILED; + } else { + return ZAUTH_FAILED; /* didn't decode correctly */ } + /* Check the cryptographic checksum. */ #ifdef NOENCRYPTION our_checksum = 0; #else - our_checksum = (ZChecksum_t)des_quad_cksum(notice->z_packet, NULL, - notice->z_default_format+ - strlen(notice->z_default_format)+1- - notice->z_packet, 0, cred.session); + checksum = compute_checksum(notice, dat.session); #endif - /* if mismatched checksum, then the packet was corrupted */ - if (our_checksum == notice->z_checksum) { - return ZAUTH_YES; + if (checksum != notice->z_checksum) + return ZAUTH_CKSUM_FAILED; + + /* Record the session key, expiry time, and source principal in the + * hash table, so we can do a fast check next time. */ + add_session_key(&ticket, dat.session, srcprincipal, + (time_t)(dat.time_sec + dat.life * 5 * 60)); + + return ZAUTH_YES; + +#else /* !ZEPHYR_USES_KERBEROS */ + return (notice->z_auth) ? ZAUTH_YES : ZAUTH_NO; +#endif +} + +#ifdef ZEPHYR_USES_KERBEROS + +static int hash_ticket(p, len) + unsigned char *p; + int len; +{ + unsigned long hashval = 0, g; + + for (; len > 0; p++, len--) { + hashval = (hashval << 4) + *p; + g = hashval & 0xf0000000; + if (g) { + hashval ^= g >> 24; + hashval ^= g; + } } - else { - syslog (LOG_DEBUG, "checksum mismatch->AUTH_FAILED (from %s)", - inet_ntoa (from->sin_addr)); - return ZAUTH_FAILED; + return hashval % HASHTAB_SIZE; +} + +static void add_session_key(ticket, session_key, srcprincipal, expires) + KTEXT ticket; + C_Block session_key; + char *srcprincipal; + time_t expires; +{ + Hash_entry *entry; + int hashval; + + /* If we can't allocate memory for the hash table entry, just forget + * about it. */ + entry = (Hash_entry *) malloc(sizeof(Hash_entry) - 1 + ticket->length); + if (!entry) + return; + + /* Initialize the new entry. */ + memcpy(entry->session_key, session_key, sizeof(entry->session_key)); + strcpy(entry->srcprincipal, srcprincipal); + entry->expires = expires; + entry->ticket_len = ticket->length; + memcpy(entry->ticket, ticket->dat, ticket->length * sizeof(unsigned char)); + + /* Insert the new entry in the hash table. */ + hashval = hash_ticket(ticket->dat, ticket->length); + entry->next = hashtab[hashval]; + hashtab[hashval] = entry; +} + +static int find_session_key(ticket, key, srcprincipal) + KTEXT ticket; + C_Block key; + char *srcprincipal; +{ + unsigned char *dat; + int hashval, len; + Hash_entry *entry; + + dat = ticket->dat; + len = ticket->length; + hashval = hash_ticket(dat, len); + + for (entry = hashtab[hashval]; entry; entry = entry->next) { + if (entry->ticket_len == len && memcmp(entry->ticket, dat, len) == 0) { + memcpy(key, entry->session_key, sizeof(entry->session_key)); + strcpy(srcprincipal, entry->srcprincipal); + return 0; + } } -} -#endif /* KERBEROS */ + return -1; +} + +static ZChecksum_t compute_checksum(notice, session_key) + ZNotice_t *notice; + C_Block session_key; +{ +#ifdef NOENCRYPTION + return 0; +#else + ZChecksum_t checksum; + char *cstart, *cend, *hstart = notice->z_packet, *hend = notice->z_message; + + cstart = notice->z_default_format + strlen(notice->z_default_format) + 1; + cend = cstart + strlen(cstart) + 1; + checksum = des_quad_cksum(hstart, NULL, cstart - hstart, 0, session_key); + checksum ^= des_quad_cksum(cend, NULL, hend - cend, 0, session_key); + checksum ^= des_quad_cksum(notice->z_message, NULL, notice->z_message_len, + 0, session_key); + return checksum; +#endif +} + +static ZChecksum_t compute_rlm_checksum(notice, session_key) + ZNotice_t *notice; + C_Block session_key; +{ +#ifdef NOENCRYPTION + return 0; +#else + ZChecksum_t checksum; + char *cstart, *cend, *hstart = notice->z_packet, *hend = notice->z_message; + + cstart = notice->z_default_format + strlen(notice->z_default_format) + 1; + cend = cstart + strlen(cstart) + 1; + checksum = des_quad_cksum(hstart, NULL, cstart - hstart, 0, session_key); + return checksum; +#endif +} + +void sweep_ticket_hash_table(arg) + void *arg; +{ + int i; + Hash_entry **ptr, *entry; + + for (i = 0; i < HASHTAB_SIZE; i++) { + ptr = &hashtab[i]; + while (*ptr) { + entry = *ptr; + if (entry->expires < NOW) { + *ptr = entry->next; + free(entry); + } else { + ptr = &(*ptr)->next; + } + } + } + timer_set_rel(SWEEP_INTERVAL, sweep_ticket_hash_table, NULL); +} + +#endif /* ZEPHYR_USES_KERBEROS */ + diff --git a/server/kstuff.c.auth b/server/kstuff.c.auth deleted file mode 100644 index f81da75..0000000 --- a/server/kstuff.c.auth +++ /dev/null @@ -1,363 +0,0 @@ -#ifdef KERBEROS -/* This file is part of the Project Athena Zephyr Notification System. - * It contains functions for dealing with Kerberos functions in the server. - * - * Created by: John T Kohl - * - * Copyright (c) 1988 by the Massachusetts Institute of Technology. - * For copying and distribution information, see the file - * "mit-copyright.h". - */ -/* - * $Source$ - * $Header$ - */ - -#ifndef lint -#ifndef SABER -static char rcsid_kstuff_c[] = "$Id$"; -#endif -#endif - -#include "zserver.h" - -#include <ctype.h> -#include <netdb.h> -#include <string.h> - -#include <zephyr/zephyr_internal.h> -#ifdef KERBEROS -#include <zephyr/krb_err.h> -#endif - -/* Keep a hash table mapping tickets to session keys, so we can do a fast - * check of the cryptographic checksum without doing and DES decryptions. - * Also remember the expiry time of the ticket, so that we can sweep the - * table periodically. */ - -#define HASHTAB_SIZE 4091 - -typedef struct hash_entry Hash_entry; - -/* The ticket comes at the end, in a variable-length array. */ -struct hash_entry { - C_Block session_key; - time_t expires; - char srcprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4]; - Hash_entry *next; - int ticket_len; - unsigned char ticket[1]; -}; - -Hash_entry *hashtab[HASHTAB_SIZE]; - -static char tkt_file[] = ZEPHYR_TKFILE; - -#ifdef __STDC__ -static int hash_ticket(unsigned char *, int); -static void add_session_key(KTEXT, C_Block, char *, time_t); -static int find_session_key(KTEXT, C_Block, char *); -#else -static int hash_ticket(); -static void add_session_key(); -static int find_session_key(); -#endif - -/* - * GetKerberosData - * - * get ticket from file descriptor and decode it. - * Return KFAILURE if we barf on reading the ticket, else return - * the value of rd_ap_req() applied to the ticket. - */ -int -GetKerberosData(fd, haddr, kdata, service, srvtab) - int fd; /* file descr. to read from */ - struct in_addr haddr; /* address of foreign host on fd */ - AUTH_DAT *kdata; /* kerberos data (returned) */ - char *service; /* service principal desired */ - char *srvtab; /* file to get keys from */ -{ - char p[20]; - KTEXT_ST ticket; /* will get Kerberos ticket from client */ - int i; - char instance[INST_SZ]; - - /* - * Get the Kerberos ticket. The first few characters, terminated - * by a blank, should give us a length; then get than many chars - * which will be the ticket proper. - */ - for (i=0; i<20; i++) { - if (read(fd, &p[i], 1) != 1) { - syslog(LOG_WARNING,"bad read tkt len"); - return(KFAILURE); - } - if (p[i] == ' ') { - p[i] = '\0'; - break; - } - } - ticket.length = atoi(p); - if ((i==20) || (ticket.length<=0) || (ticket.length>MAX_KTXT_LEN)) { - syslog(LOG_WARNING,"bad tkt len %d",ticket.length); - return(KFAILURE); - } - for (i=0; i<ticket.length; i++) { - if (read(fd, (caddr_t) &(ticket.dat[i]), 1) != 1) { - syslog(LOG_WARNING,"bad tkt read"); - return(KFAILURE); - } - } - /* - * now have the ticket. use it to get the authenticated - * data from Kerberos. - */ - (void) strcpy(instance,"*"); /* let Kerberos fill it in */ - - return(krb_rd_req(&ticket, service, instance, haddr.s_addr, - kdata, srvtab ? srvtab : "")); -} - -/* - * SendKerberosData - * - * create and transmit a ticket over the file descriptor for service.host - * return failure codes if appropriate, or 0 if we - * get the ticket and write it to the file descriptor - */ - -int -SendKerberosData(fd, ticket, service, host) - int fd; /* file descriptor to write onto */ - KTEXT ticket; /* where to put ticket (return) */ - char *service; /* service name, foreign host */ - char *host; -{ - int rem; - char p[32]; - char krb_realm[REALM_SZ]; - int written; - int size_to_write; - - rem = krb_get_lrealm(krb_realm,1); - if (rem != KSUCCESS) - return rem + krb_err_base; - - rem = krb_mk_req( ticket, service, host, krb_realm, (u_long)0 ); - if (rem != KSUCCESS) - return rem + krb_err_base; - - (void) sprintf(p,"%d ",ticket->length); - size_to_write = strlen (p); - if ((written = write(fd, p, size_to_write)) != size_to_write) - if (written < 0) - return errno; - else - return ZSRV_PKSHORT; - if ((written = write(fd, (caddr_t) (ticket->dat), ticket->length)) != ticket->length) - if (written < 0) - return errno; - else - return ZSRV_PKSHORT; - - return 0; -} - -/* Hack to replace the kerberos library's idea of the ticket file with - our idea */ -char * -tkt_string() -{ - return tkt_file; -} - -int -ZCheckAuthentication(notice, from) - ZNotice_t *notice; - struct sockaddr_in *from; -{ -#ifdef Z_HaveKerberos - int result, len; - char srcprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4]; - KTEXT_ST authent, ticket; - AUTH_DAT dat; - ZChecksum_t our_checksum; - unsigned long cksum; - CREDENTIALS cred; - C_Block session_key; - - if (!notice->z_auth) - return (ZAUTH_NO); - - /* Check for bogus authentication data length. */ - if (notice->z_authent_len <= 0) - return(ZAUTH_FAILED); - - /* Read in the authentication data. */ - if (ZReadAscii(notice->z_ascii_authent, - strlen(notice->z_ascii_authent)+1, - (unsigned char *)authent.dat, - notice->z_authent_len) == ZERR_BADFIELD) { - return (ZAUTH_FAILED); - } - authent.length = notice->z_authent_len; - - /* Copy the ticket out of the authentication data. */ - if (krb_find_ticket(&authent, &ticket) != RD_AP_OK) - return (ZAUTH_FAILED); - - /* Try to do a fast check against the cryptographic checksum. */ - if (find_session_key(&ticket, session_key, srcprincipal) >= 0) { - if (strcmp(srcprincipal, notice->z_sender) != 0) - return (ZAUTH_FAILED); - if (notice->z_time.tv_sec - NOW > CLOCK_SKEW) - return (ZAUTH_FAILED); -#ifdef NOENCRYPTION - our_checksum = 0; -#else - len = notice->z_default_format + strlen(notice->z_default_format) - + 1 - notice->z_packet; - result = des_quad_cksum(notice->z_packet, NULL, len, 0, session_key); - result ^= des_quad_cksum(notice->z_message, NULL, notice->z_message_len, - 0, session_key); - our_checksum = (ZChecksum_t) result; -#endif - /* If checksum matches, packet is authentic. Otherwise, check - * the authenticator as if we didn't have the session key cached - * and return ZAUTH_CKSUM_FAILED. This is a rare case (since the - * ticket isn't cached after a checksum failure), so don't worry - * about the extra des_quad_cksum() call. */ - if (our_checksum == notice->z_checksum) - return (ZAUTH_YES); - } - - /* We don't have the session key cached; do it the long way. */ - result = krb_rd_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, - from->sin_addr.s_addr, &dat, SERVER_SRVTAB); - if (result == RD_AP_OK) { - (void) memcpy((char *)__Zephyr_session, (char *)dat.session, - sizeof(C_Block)); - (void) sprintf(srcprincipal, "%s%s%s@%s", dat.pname, - dat.pinst[0]?".":"", dat.pinst, dat.prealm); - if (strcmp(srcprincipal, notice->z_sender)) - return (ZAUTH_FAILED); - } else { - return (ZAUTH_FAILED); /* didn't decode correctly */ - } - - /* Check the cryptographic checksum. */ -#ifdef NOENCRYPTION - our_checksum = 0; -#else - len = notice->z_default_format + strlen(notice->z_default_format) - + 1 - notice->z_packet; - cksum = des_quad_cksum(notice->z_packet, NULL, len, 0, dat.session); - our_checksum = (ZChecksum_t) cksum; -#endif - if (our_checksum != notice->z_checksum) - return (ZAUTH_CKSUM_FAILED); - - /* Record the session key, expiry time, and source principal in the - * hash table, so we can do a fast check next time. */ - add_session_key(&ticket, dat.session, srcprincipal, - (time_t)(dat.time_sec + dat.life * 5 * 60)); - - return (ZAUTH_YES); - -#else /* not Z_HaveKerberos */ - return (notice->z_auth ? ZAUTH_YES : ZAUTH_NO); -#endif -} - -static int hash_ticket(p, len) - unsigned char *p; - int len; -{ - unsigned long hashval = 0, g; - - for (; len > 0; p++, len--) { - hashval = (hashval << 4) + *p; - g = hashval & 0xf0000000; - if (g) { - hashval ^= g >> 24; - hashval ^= g; - } - } - return hashval % HASHTAB_SIZE; -} - -static void add_session_key(ticket, session_key, srcprincipal, expires) - KTEXT ticket; - C_Block session_key; - char *srcprincipal; - time_t expires; -{ - Hash_entry *entry; - int hashval; - - /* If we can't allocate memory for the hash table entry, just forget - * about it. */ - entry = (Hash_entry *) xmalloc(sizeof(Hash_entry) - 1 + ticket->length); - if (!entry) - return; - - /* Initialize the new entry. */ - memcpy(entry->session_key, session_key, sizeof(entry->session_key)); - strcpy(entry->srcprincipal, srcprincipal); - entry->expires = expires; - entry->ticket_len = ticket->length; - memcpy(entry->ticket, ticket->dat, ticket->length * sizeof(unsigned char)); - - /* Insert the new entry in the hash table. */ - hashval = hash_ticket(ticket->dat, ticket->length); - entry->next = hashtab[hashval]; - hashtab[hashval] = entry; -} - -static int find_session_key(ticket, key, srcprincipal) - KTEXT ticket; - C_Block key; - char *srcprincipal; -{ - unsigned char *dat; - int hashval, len; - Hash_entry *entry; - - dat = ticket->dat; - len = ticket->length; - hashval = hash_ticket(dat, len); - - for (entry = hashtab[hashval]; entry; entry = entry->next) { - if (entry->ticket_len == len && memcmp(entry->ticket, dat, len) == 0) { - memcpy(key, entry->session_key, sizeof(entry->session_key)); - strcpy(srcprincipal, entry->srcprincipal); - return 0; - } - } - return -1; -} - -void sweep_ticket_hash_table(arg) - void *arg; -{ - int i; - Hash_entry **ptr, *entry; - - for (i = 0; i < HASHTAB_SIZE; i++) { - ptr = &hashtab[i]; - while (*ptr) { - entry = *ptr; - if (entry->expires < NOW) { - *ptr = entry->next; - free(entry); - } else { - ptr = &(*ptr)->next; - } - } - } - timer_set_rel(SWEEP_INTERVAL, sweep_ticket_hash_table, NULL); -} - -#endif /* KERBEROS */ - diff --git a/server/main.c b/server/main.c index 3420d06..9978bbd 100644 --- a/server/main.c +++ b/server/main.c @@ -12,10 +12,13 @@ */ #include <zephyr/mit-copyright.h> +#include "zserver.h" +#include <sys/socket.h> +#include <sys/resource.h> #ifndef lint #ifndef SABER -static char rcsid_main_c[] = +static const char rcsid_main_c[] = "$Id$"; #endif #endif @@ -47,91 +50,58 @@ static char rcsid_main_c[] = (if the client has not acknowledged a packet after a given timeout). */ -#include "zserver.h" -/* which includes - zephyr/zephyr.h - <errno.h> - <sys/types.h> - <netinet/in.h> - <sys/time.h> - <stdio.h> - <sys/file.h> - <syslog.h> - <strings.h> - <signal.h> - timer.h - zsrv_err.h - */ - -#include <netdb.h> -#include <sys/socket.h> -#include <sys/param.h> -#include <sys/ioctl.h> -#include <sys/resource.h> -#include <sys/wait.h> -#ifdef POSIX -#include <termios.h> -#endif - -#ifdef POSIX -#define SIGNAL_RETURN_TYPE void -#define SIG_RETURN return -#else -#define SIGNAL_RETURN_TYPE int -#define SIG_RETURN return(0) -#endif - -#if !defined(__SABER__) && (defined (vax) || defined (ibm032)) -#define MONCONTROL moncontrol -#else -#define MONCONTROL (void) -#endif - #define EVER (;;) /* don't stop looping */ -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -static int do_net_setup P((void)), initialize P((void)); -static void usage P((void)), do_reset P((void)); -static SIGNAL_RETURN_TYPE bye P((int)), - dbug_on P((int)), dbug_off P((int)), - sig_dump_db P((int)), sig_dump_strings P((int)), - reset P((int)), reap P((int)); -static void read_from_dump P((char *dumpfile)); -static void dump_db P((void)), dump_strings P((void)); +static int do_net_setup __P((void)); +static int initialize __P((void)); +static void usage __P((void)); +static void do_reset __P((void)); +static RETSIGTYPE bye __P((int)); +static RETSIGTYPE dbug_on __P((int)); +static RETSIGTYPE dbug_off __P((int)); +static RETSIGTYPE sig_dump_db __P((int)); +static RETSIGTYPE sig_dump_strings __P((int)); +static RETSIGTYPE reset __P((int)); +static RETSIGTYPE reap __P((int)); +static void read_from_dump __P((char *dumpfile)); +static void dump_db __P((void)); +static void dump_strings __P((void)); #ifndef DEBUG -static void detach P((void)); +static void detach __P((void)); #endif -extern void perror P((Zconst char *)); - -#undef P - static short doreset = 0; /* if it becomes 1, perform reset functions */ +int nfds; /* max file descriptor for select() */ int srv_socket; /* dgram socket for clients and other servers */ int bdump_socket = -1; /* brain dump socket fd (closed most of the time) */ fd_set interesting; /* the file descrips we are listening to right now */ -int nfildes; /* number to look at in select() */ -struct sockaddr_in sock_sin; /* address of the socket */ -struct timeval nexthost_tv; /* time till next timeout for select */ +struct sockaddr_in srv_addr; /* address of the socket */ -ZNotAcked_t *nacklist; /* list of packets waiting for ack's */ +Unacked *nacklist = NULL; /* list of packets waiting for ack's */ -u_short hm_port; /* the port # of the host manager */ +unsigned short hm_port; /* host manager receiver port */ +unsigned short hm_srv_port; /* host manager server sending port */ char *programname; /* set to the basename of argv[0] */ char myname[MAXHOSTNAMELEN]; /* my host name */ +#ifndef ZEPHYR_USES_HESIOD +char list_file[128]; +#endif +#ifdef ZEPHYR_USES_KERBEROS +char srvtab_file[128]; +char my_realm[REALM_SZ]; +static char tkt_file[128]; +#endif +char acl_dir[128]; +char subs_file[128]; + int zdebug; #ifdef DEBUG_MALLOC int dump_malloc_stats = 0; @@ -147,259 +117,247 @@ static int dump_db_flag = 0; static int dump_strings_flag = 0; u_long npackets; /* number of packets processed */ -long uptime; /* when we started operations */ +time_t uptime; /* when we started operations */ static int nofork; struct in_addr my_addr; -char *bdump_version = "1.1"; +char *bdump_version = "1.2"; int main(argc, argv) - int argc; - char **argv; + int argc; + char **argv; { - int nfound; /* #fildes ready on select */ - fd_set readable; - struct timeval *tvp; - int init_from_dump = 0; - char *dumpfile; -#ifdef POSIX - struct sigaction action; -#endif - - - int optchar; /* option processing */ - extern char *optarg; - extern int optind; - - /* set name */ - if (programname = strrchr(argv[0],'/')) - programname++; - else programname = argv[0]; - - /* process arguments */ - - while ((optchar = getopt(argc, argv, "dsnv:f:")) != EOF) { - switch(optchar) { - case 'd': - zdebug = 1; - break; + int nfound; /* #fildes ready on select */ + fd_set readable; + struct timeval tv; + int init_from_dump = 0; + char *dumpfile; +#ifdef _POSIX_VERSION + struct sigaction action; +#endif + int optchar; /* option processing */ + extern char *optarg; + extern int optind; + +#ifndef ZEPHYR_USES_HESIOD + sprintf(list_file, "%s/%s", CONFDIR, SERVER_LIST_FILE); +#endif +#ifdef ZEPHYR_USES_KERBEROS + sprintf(srvtab_file, "%s/%s", CONFDIR, ZEPHYR_SRVTAB); + sprintf(tkt_file, "%s/%s", CONFDIR, ZEPHYR_TKFILE); +#endif + sprintf(acl_dir, "%s/%s", CONFDIR, ZEPHYR_ACL_DIR); + sprintf(subs_file, "%s/%s", CONFDIR, DEFAULT_SUBS_FILE); + + /* set name */ + programname = strrchr(argv[0],'/'); + programname = (programname) ? programname + 1 : argv[0]; + + /* process arguments */ + while ((optchar = getopt(argc, argv, "dsnv:f:k:")) != EOF) { + switch(optchar) { + case 'd': + zdebug = 1; + break; #ifdef DEBUG - case 's': - zalone = 1; - break; -#endif - case 'n': - nofork = 1; - break; - case 'v': - bdump_version = optarg; - break; - case 'f': - init_from_dump = 0; - dumpfile = optarg; - break; - case '?': - default: - usage(); - /*NOTREACHED*/ - } + case 's': + zalone = 1; + break; +#endif + case 'n': + nofork = 1; + break; + case 'k': +#ifdef ZEPHYR_USES_KERBEROS + strncpy(my_realm, optarg, REALM_SZ); +#endif + break; + case 'v': + bdump_version = optarg; + break; + case 'f': + init_from_dump = 0; + dumpfile = optarg; + break; + case '?': + default: + usage(); + /*NOTREACHED*/ } + } -#ifdef KERBEROS - /* if there is no readable srvtab and we are not standalone, there - is no possible way we can succeed, so we exit */ +#ifdef ZEPHYR_USES_KERBEROS + /* if there is no readable srvtab and we are not standalone, there + is no possible way we can succeed, so we exit */ - if (access(ZEPHYR_SRVTAB, R_OK) + if (access(srvtab_file, R_OK) #ifdef DEBUG - && !zalone + && !zalone #endif /* DEBUG */ - ) { - fprintf(stderr, "NO ZEPHYR SRVTAB (%s) available; exiting\n", - ZEPHYR_SRVTAB); - exit(1); + ) { + fprintf(stderr, "NO ZEPHYR SRVTAB (%s) available; exiting\n", + srvtab_file); + exit(1); + } + /* Use local realm if not specified on command line. */ + if (!*my_realm) { + if (krb_get_lrealm(my_realm, 1) != KSUCCESS) { + fputs("Couldn't get local Kerberos realm; exiting.\n", stderr); + exit(1); } -#endif /* KERBEROS */ + } +#endif /* ZEPHYR_USES_KERBEROS */ #ifndef DEBUG - if (!nofork) - detach(); + if (!nofork) + detach(); #endif /* DEBUG */ - /* open log */ - OPENLOG(programname, LOG_PID, LOG_LOCAL6); + /* open log */ + OPENLOG(programname, LOG_PID, LOG_LOCAL6); #if defined (DEBUG) && 0 - if (zalone) - syslog(LOG_DEBUG, "standalone operation"); + if (zalone) + syslog(LOG_DEBUG, "standalone operation"); #endif #if 0 - if (zdebug) - syslog(LOG_DEBUG, "debugging on"); + if (zdebug) + syslog(LOG_DEBUG, "debugging on"); #endif - /* set up sockets & my_addr and myname, - find other servers and set up server table, initialize queues - for retransmits, initialize error tables, - set up restricted classes */ - - /* Initialize t_local for other uses */ - (void) gettimeofday(&t_local, (struct timezone *)0); + /* set up sockets & my_addr and myname, + find other servers and set up server table, initialize queues + for retransmits, initialize error tables, + set up restricted classes */ - if (initialize()) - exit(1); + /* Initialize t_local for other uses */ + gettimeofday(&t_local, NULL); - if (init_from_dump) - read_from_dump(dumpfile); + if (initialize()) + exit(1); - /* Seed random number set. */ - srandom (getpid () ^ time (0)); + if (init_from_dump) + read_from_dump(dumpfile); -#ifndef __SABER__ - /* chdir to somewhere where a core dump will survive */ - if (chdir("/usr/tmp") != 0) - syslog(LOG_ERR,"chdir failed (%m) (execution continuing)"); + /* Seed random number set. */ + srandom(getpid() ^ time(0)); -#if 0 - /* - * Many systems don't implement setpriority() as is done under BSD, - * and the kernel scheduler will appropriately swap in the processes - * that are needed. - */ - if (setpriority(PRIO_PROCESS, getpid(), -10)) - syslog(LOG_ERR,"setpriority failed (%m)"); -#endif -#endif + /* chdir to somewhere where a core dump will survive */ + if (chdir(TEMP_DIRECTORY) != 0) + syslog(LOG_ERR, "chdir failed (%m) (execution continuing)"); - FD_ZERO(&interesting); - FD_SET(srv_socket, &interesting); + FD_ZERO(&interesting); + FD_SET(srv_socket, &interesting); - nfildes = srv_socket + 1; + nfds = srv_socket + 1; -#ifdef POSIX - action.sa_flags = 0; - sigemptyset(&action.sa_mask); +#ifdef _POSIX_VERSION + action.sa_flags = 0; + sigemptyset(&action.sa_mask); - action.sa_handler = bye; - sigaction(SIGINT, &action, NULL); - sigaction(SIGTERM, &action, NULL); + action.sa_handler = bye; + sigaction(SIGINT, &action, NULL); + sigaction(SIGTERM, &action, NULL); - action.sa_handler = dbug_on; - sigaction(SIGUSR1, &action, NULL); + action.sa_handler = dbug_on; + sigaction(SIGUSR1, &action, NULL); - action.sa_handler = dbug_off; - sigaction(SIGUSR2, &action, NULL); + action.sa_handler = dbug_off; + sigaction(SIGUSR2, &action, NULL); - action.sa_handler = reap; - sigaction(SIGCHLD, &action, NULL); + action.sa_handler = reap; + sigaction(SIGCHLD, &action, NULL); - action.sa_handler = sig_dump_db; - sigaction(SIGFPE, &action, NULL); - sigaction(SIGXCPU, &action, NULL); + action.sa_handler = sig_dump_db; + sigaction(SIGFPE, &action, NULL); #ifdef SIGEMT - action.sa_handler = sig_dump_strings; - sigaction(SIGEMT, &action, NULL); + action.sa_handler = sig_dump_strings; + sigaction(SIGEMT, &action, NULL); #endif - action.sa_handler = reset; - sigaction(SIGHUP, &action, NULL); + action.sa_handler = reset; + sigaction(SIGHUP, &action, NULL); #else /* !posix */ - (void) signal(SIGINT, bye); - (void) signal(SIGTERM, bye); - (void) signal(SIGUSR1, dbug_on); - (void) signal(SIGUSR2, dbug_off); - (void) signal(SIGCHLD, reap); - (void) signal(SIGFPE, sig_dump_db); - (void) signal(SIGXCPU, sig_dump_db); + signal(SIGINT, bye); + signal(SIGTERM, bye); + signal(SIGUSR1, dbug_on); + signal(SIGUSR2, dbug_off); + signal(SIGCHLD, reap); + signal(SIGFPE, sig_dump_db); #ifdef SIGEMT - (void) signal(SIGEMT, sig_dump_strings); + signal(SIGEMT, sig_dump_strings); #endif - (void) signal(SIGHUP, reset); -#endif /* POSIX */ + signal(SIGHUP, reset); +#endif /* _POSIX_VERSION */ - syslog(LOG_NOTICE, "Ready for action"); + syslog(LOG_NOTICE, "Ready for action"); - /* Reinitialize t_local now that initialization is done. */ - (void) gettimeofday(&t_local, (struct timezone *)0); - /* GO! */ - uptime = NOW; + /* Reinitialize t_local now that initialization is done. */ + gettimeofday(&t_local, NULL); + uptime = NOW; +#ifdef ZEPHYR_USES_KERBEROS + timer_set_rel(SWEEP_INTERVAL, sweep_ticket_hash_table, NULL); +#endif #ifdef DEBUG_MALLOC - malloc_inuse(&m_size); -#endif - for EVER { - if (doreset) - do_reset(); - - if (dump_db_flag) - dump_db(); - if (dump_strings_flag) - dump_strings(); - - nexthost_tv.tv_usec = 0; - tvp = &nexthost_tv; - - if (nexttimo != 0L) { - nexthost_tv.tv_sec = nexttimo - NOW; - if (nexthost_tv.tv_sec <= 0) { - /* timeout has passed! */ - /* so we process one timeout, then pop to - select, polling for input. This way we get - work done even if swamped with many - timeouts */ - /* this will reset nexttimo */ - (void) timer_process(); - nexthost_tv.tv_sec = 0; - } - } else { /* no timeouts to process */ - nexthost_tv.tv_sec = 15; - } - readable = interesting; - if (msgs_queued()) { - /* when there is input in the queue, we - artificially set up to pick up the input */ - nfound = 1; - FD_ZERO(&readable); - } else - nfound = select(nfildes, &readable, (fd_set *) 0, - (fd_set *) 0, tvp); - - /* Initialize t_local for other uses */ - (void) gettimeofday(&t_local, (struct timezone *)0); + malloc_inuse(&m_size); +#endif + for EVER { + if (doreset) + do_reset(); + + if (dump_db_flag) + dump_db(); + if (dump_strings_flag) + dump_strings(); + + readable = interesting; + if (msgs_queued()) { + /* when there is input in the queue, we + artificially set up to pick up the input */ + nfound = 1; + FD_ZERO(&readable); + } else { + nfound = select(nfds, &readable, NULL, NULL, timer_timeout(&tv)); + } + + /* Initialize t_local for other uses */ + gettimeofday(&t_local, (struct timezone *)0); - /* don't flame about EINTR, since a SIGUSR1 or SIGUSR2 - can generate it by interrupting the select */ - if (nfound < 0) { - if (errno != EINTR) - syslog(LOG_WARNING, "select error: %m"); + /* don't flame about EINTR, since a SIGUSR1 or SIGUSR2 + can generate it by interrupting the select */ + if (nfound < 0) { + if (errno != EINTR) + syslog(LOG_WARNING, "select error: %m"); #ifdef DEBUG_MALLOC - if (dump_malloc_stats) { - unsigned long foo,histid2; - dump_malloc_stats = 0; - foo = malloc_inuse(&histid2); - printf("Total inuse: %d\n",foo); - malloc_list(2,m_size,histid2); - } -#endif - continue; - } - if (nfound == 0) - /* either we timed out or we were just - polling for input. Either way we want to continue - the loop, and process the next timeout */ - continue; - else { - if ((bdump_socket >= 0) && - FD_ISSET(bdump_socket,&readable)) - bdump_send(); - else if (msgs_queued() || - FD_ISSET(srv_socket, &readable)) { - handle_packet(); - } else - syslog(LOG_ERR, "select weird?!?!"); - } + if (dump_malloc_stats) { + unsigned long foo,histid2; + + dump_malloc_stats = 0; + foo = malloc_inuse(&histid2); + printf("Total inuse: %d\n",foo); + malloc_list(2,m_size,histid2); + } +#endif + continue; + } + + if (nfound == 0) { + /* either we timed out or we were just + polling for input. Either way we want to continue + the loop, and process the next timeout */ + continue; + } else { + if (bdump_socket >= 0 && FD_ISSET(bdump_socket,&readable)) + bdump_send(); + else if (msgs_queued() || FD_ISSET(srv_socket, &readable)) + handle_packet(); + else + syslog(LOG_ERR, "select weird?!?!"); } + } } /* Initialize net stuff. @@ -412,49 +370,35 @@ main(argc, argv) static int initialize() { - if (do_net_setup()) - return(1); + if (do_net_setup()) + return(1); - server_init(); + server_init(); -#if 0 - if (!(nacklist = (ZNotAcked_t *) xmalloc(sizeof(ZNotAcked_t)))) { - /* unrecoverable */ - syslog(LOG_CRIT, "nacklist malloc"); - abort(); - } -#else - { - static ZNotAcked_t not_acked_head; - nacklist = ¬_acked_head; - } +#ifdef ZEPHYR_USES_KERBEROS + krb_set_tkt_string(tkt_file); #endif - (void) memset((caddr_t) nacklist, 0, sizeof(ZNotAcked_t)); - nacklist->q_forw = nacklist->q_back = nacklist; - - nexttimo = 1L; /* trigger the timers when we hit - the FOR loop */ + realm_init(); - (void) ZInitialize(); /* set up the library */ - (void) init_zsrv_err_tbl(); /* set up err table */ + ZSetServerState(1); + ZInitialize(); /* set up the library */ + init_zsrv_err_tbl(); /* set up err table */ - (void) ZSetServerState(1); - (void) ZSetFD(srv_socket); /* set up the socket as the - input fildes */ + ZSetFD(srv_socket); /* set up the socket as the input fildes */ - /* set up default strings */ + /* set up default strings */ - class_control = make_zstring(ZEPHYR_CTL_CLASS, 1); - class_admin = make_zstring(ZEPHYR_ADMIN_CLASS, 1); - class_hm = make_zstring(HM_CTL_CLASS, 1); - class_ulogin = make_zstring(LOGIN_CLASS, 1); - class_ulocate = make_zstring(LOCATE_CLASS, 1); - wildcard_instance = make_zstring(WILDCARD_INSTANCE, 1); - empty = make_zstring("", 0); + class_control = make_string(ZEPHYR_CTL_CLASS, 1); + class_admin = make_string(ZEPHYR_ADMIN_CLASS, 1); + class_hm = make_string(HM_CTL_CLASS, 1); + class_ulogin = make_string(LOGIN_CLASS, 1); + class_ulocate = make_string(LOCATE_CLASS, 1); + wildcard_instance = make_string(WILDCARD_INSTANCE, 1); + empty = make_string("", 0); - /* restrict certain classes */ - access_init(); - return(0); + /* restrict certain classes */ + access_init(); + return 0; } /* @@ -464,62 +408,59 @@ initialize() static int do_net_setup() { - struct servent *sp; - struct hostent *hp; - char hostname[MAXHOSTNAMELEN+1]; - int flags; - - if (gethostname(hostname, MAXHOSTNAMELEN+1)) { - syslog(LOG_ERR, "no hostname: %m"); - return(1); - } - if (!(hp = gethostbyname(hostname))) { - syslog(LOG_ERR, "no gethostbyname repsonse"); - (void) strncpy(myname, hostname, MAXHOSTNAMELEN); - return(1); - } - (void) strncpy(myname, hp->h_name, MAXHOSTNAMELEN); - (void) memcpy((caddr_t) &my_addr, (caddr_t) hp->h_addr, - sizeof(hp->h_addr)); - - (void) setservent(1); /* keep file/connection open */ - - if (!(sp = getservbyname(SERVER_SVCNAME, "udp"))) { - syslog(LOG_ERR, "%s/udp unknown",SERVER_SVCNAME); - return(1); - } - (void) memset((caddr_t) &sock_sin, 0, sizeof(sock_sin)); - sock_sin.sin_port = sp->s_port; - - if (!(sp = getservbyname(HM_SVCNAME, "udp"))) { - syslog(LOG_ERR, "%s/udp unknown", HM_SVCNAME); - return(1); - } - hm_port = sp->s_port; + struct servent *sp; + struct hostent *hp; + char hostname[MAXHOSTNAMELEN+1]; + int flags; + + if (gethostname(hostname, MAXHOSTNAMELEN + 1)) { + syslog(LOG_ERR, "no hostname: %m"); + return 1; + } + hp = gethostbyname(hostname); + if (!hp) { + syslog(LOG_ERR, "no gethostbyname repsonse"); + strncpy(myname, hostname, MAXHOSTNAMELEN); + return 1; + } + strncpy(myname, hp->h_name, MAXHOSTNAMELEN); + memcpy(&my_addr, hp->h_addr, sizeof(hp->h_addr)); - (void) endservent(); + setservent(1); /* keep file/connection open */ + + memset(&srv_addr, 0, sizeof(srv_addr)); + srv_addr.sin_family = AF_INET; + sp = getservbyname(SERVER_SVCNAME, "udp"); + srv_addr.sin_port = (sp) ? sp->s_port : SERVER_SVC_FALLBACK; + + sp = getservbyname(HM_SVCNAME, "udp"); + hm_port = (sp) ? sp->s_port : HM_SVC_FALLBACK; - if ((srv_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - syslog(LOG_ERR, "client_sock failed: %m"); - return(1); - } - if (bind(srv_socket, (struct sockaddr *) &sock_sin, - sizeof(sock_sin)) < 0) { - syslog(LOG_ERR, "client bind failed: %m"); - return(1); - } + sp = getservbyname(HM_SRV_SVCNAME, "udp"); + hm_srv_port = (sp) ? sp->s_port : HM_SRV_SVC_FALLBACK; + + srv_socket = socket(AF_INET, SOCK_DGRAM, 0); + if (srv_socket < 0) { + syslog(LOG_ERR, "client_sock failed: %m"); + return 1; + } + if (bind(srv_socket, (struct sockaddr *) &srv_addr, + sizeof(srv_addr)) < 0) { + syslog(LOG_ERR, "client bind failed: %m"); + return 1; + } - /* set not-blocking */ -#ifdef POSIX - flags = fcntl(srv_socket, F_GETFL); - flags |= O_NONBLOCK; - (void) fcntl(srv_socket, F_SETFL, flags); + /* set not-blocking */ +#ifdef _POSIX_VERSION + flags = fcntl(srv_socket, F_GETFL); + flags |= O_NONBLOCK; + fcntl(srv_socket, F_SETFL, flags); #else - flags = 1; - (void) ioctl(srv_socket, FIONBIO, (caddr_t) &flags); + flags = 1; + ioctl(srv_socket, FIONBIO, &flags); #endif - return(0); + return 0; } @@ -531,186 +472,160 @@ static void usage() { #ifdef DEBUG - fprintf(stderr,"Usage: %s [-d] [-s] [-n] [-f dumpfile]\n",programname); + fprintf(stderr, "Usage: %s [-d] [-s] [-n] [-k realm] [-f dumpfile]\n", + programname); #else - fprintf(stderr,"Usage: %s [-d] [-n] [-f dumpfile]\n",programname); + fprintf(stderr, "Usage: %s [-d] [-n] [-k realm] [-f dumpfile]\n", + programname); #endif /* DEBUG */ exit(2); } -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -bye(int sig) -#else +int +packets_waiting() +{ + fd_set readable, initial; + struct timeval tv; + + if (msgs_queued()) + return 1; + FD_ZERO(&initial); + FD_SET(srv_socket, &initial); + readable = initial; + tv.tv_sec = tv.tv_usec = 0; + return (select(srv_socket + 1, &readable, NULL, NULL, &tv) > 0); +} + +static RETSIGTYPE bye(sig) - int sig; -#endif + int sig; { - server_shutdown(); /* tell other servers */ - hostm_shutdown(); /* tell our hosts */ -#ifdef KERBEROS - (void) dest_tkt(); + server_shutdown(); /* tell other servers */ + hostm_shutdown(); /* tell our hosts */ +#ifdef ZEPHYR_USES_KERBEROS + dest_tkt(); #endif - syslog(LOG_NOTICE, "goodbye (sig %d)",sig); - exit(0); - /*NOTREACHED*/ + syslog(LOG_NOTICE, "goodbye (sig %d)", sig); + exit(0); } -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -dbug_on(int sig) -#else +static RETSIGTYPE dbug_on(sig) - int sig; -#endif + int sig; { - syslog(LOG_DEBUG, "debugging turned on"); + syslog(LOG_DEBUG, "debugging turned on"); #ifdef DEBUG_MALLOC - dump_malloc_stats = 1; + dump_malloc_stats = 1; #endif - zdebug = 1; - SIG_RETURN; + zdebug = 1; } -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -dbug_off(int sig) -#else +static RETSIGTYPE dbug_off(sig) - int sig; -#endif + int sig; { - syslog(LOG_DEBUG, "debugging turned off"); + syslog(LOG_DEBUG, "debugging turned off"); #ifdef DEBUG_MALLOC - malloc_inuse(&m_size); + malloc_inuse(&m_size); #endif - zdebug = 0; - SIG_RETURN; + zdebug = 0; } int fork_for_dump = 0; -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -sig_dump_strings (int sig) -#else +static RETSIGTYPE sig_dump_strings(sig) - int sig; -#endif + int sig; { - dump_strings_flag = 1; - SIG_RETURN; + dump_strings_flag = 1; } static void dump_strings() { + char filename[128]; + FILE *fp; int oerrno = errno; - fp = fopen ("/usr/tmp/zephyr.strings", "w"); + + sprintf(filename, "%szephyr.strings", TEMP_DIRECTORY); + fp = fopen (filename, "w"); if (!fp) { - syslog (LOG_ERR, "can't open strings dump file: %m"); + syslog(LOG_ERR, "can't open strings dump file: %m"); errno = oerrno; dump_strings_flag = 0; return; } - syslog (LOG_INFO, "dumping strings to disk"); - print_zstring_table(fp); - if (fclose (fp) == EOF) - syslog (LOG_ERR, "error writing strings dump file"); + syslog(LOG_INFO, "dumping strings to disk"); + print_string_table(fp); + if (fclose(fp) == EOF) + syslog(LOG_ERR, "error writing strings dump file"); else - syslog (LOG_INFO, "dump done"); + syslog(LOG_INFO, "dump done"); oerrno = errno; dump_strings_flag = 0; return; } -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -sig_dump_db(int sig) -#else +static RETSIGTYPE sig_dump_db(sig) - int sig; -#endif + int sig; { - dump_db_flag = 1; - SIG_RETURN; + dump_db_flag = 1; } static void dump_db() { - /* dump the in-core database to human-readable form on disk */ - FILE *fp; - int oerrno = errno; - int pid; + /* dump the in-core database to human-readable form on disk */ + FILE *fp; + int oerrno = errno; + int pid; + char filename[128]; -#ifdef __SABER__ - pid = -1; -#else - if (fork_for_dump) { - MONCONTROL (0); - pid = fork (); - MONCONTROL (1); - } - else - pid = -1; -#endif - if (pid > 0) - { - dump_db_flag = 0; - return; - } - if ((fp = fopen("/usr/tmp/zephyr.db", "w")) == (FILE *)0) { - syslog(LOG_ERR, "can't open dump database"); - errno = oerrno; - dump_db_flag = 0; - return; - } - syslog(LOG_INFO, "dumping to disk"); - server_dump_servers(fp); - uloc_dump_locs(fp); - hostm_dump_hosts(fp); - class_dump_subs(fp); - syslog(LOG_INFO, "dump done"); - if (fclose(fp) == EOF) { - syslog(LOG_ERR, "can't close dump db"); - } - if (pid == 0) - exit (0); + pid = (fork_for_dump) ? fork() : -1; + if (pid > 0) { + dump_db_flag = 0; + return; + } + sprintf(filename, "%szephyr.db", TEMP_DIRECTORY); + fp = fopen(filename, "w"); + if (!fp) { + syslog(LOG_ERR, "can't open dump database"); errno = oerrno; dump_db_flag = 0; return; + } + syslog(LOG_INFO, "dumping to disk"); + server_dump_servers(fp); + uloc_dump_locs(fp); + client_dump_clients(fp); + triplet_dump_subs(fp); + realm_dump_realms(fp); + syslog(LOG_INFO, "dump done"); + if (fclose(fp) == EOF) + syslog(LOG_ERR, "can't close dump db"); + if (pid == 0) + exit(0); + errno = oerrno; + dump_db_flag = 0; } -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -reset(int sig) -#else +static RETSIGTYPE reset(sig) - int sig; -#endif + int sig; { #if 1 - zdbug((LOG_DEBUG,"reset()")); + zdbug((LOG_DEBUG,"reset()")); #endif - doreset = 1; - SIG_RETURN; + doreset = 1; } -#ifdef __GNUG__ -#define wait WaitStatus -#endif - -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -reap(int sig) -#else +static RETSIGTYPE reap(sig) - int sig; -#endif + int sig; { int oerrno = errno; -#ifdef POSIX +#ifdef _POSIX_VERSION int waitb; while (waitpid(-1, &waitb, WNOHANG) == 0) ; #else @@ -719,40 +634,39 @@ reap(sig) #endif errno = oerrno; - SIG_RETURN; } static void do_reset() { - int oerrno = errno; -#ifdef POSIX - sigset_t mask, omask; + int oerrno = errno; +#ifdef _POSIX_VERSION + sigset_t mask, omask; #else - int omask; + int omask; #endif #if 0 - zdbug((LOG_DEBUG,"do_reset()")); + zdbug((LOG_DEBUG,"do_reset()")); #endif -#ifdef POSIX - sigemptyset(&mask); - sigaddset(&mask, SIGHUP); - sigprocmask(SIG_BLOCK, &mask, &omask); +#ifdef _POSIX_VERSION + sigemptyset(&mask); + sigaddset(&mask, SIGHUP); + sigprocmask(SIG_BLOCK, &mask, &omask); #else - omask = sigblock(sigmask(SIGHUP)); + omask = sigblock(sigmask(SIGHUP)); #endif - /* reset various things in the server's state */ - subscr_reset(); - server_reset(); - access_reinit(); - syslog (LOG_INFO, "restart completed"); - doreset = 0; - errno = oerrno; -#ifdef POSIX - sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0); + /* reset various things in the server's state */ + subscr_reset(); + server_reset(); + access_reinit(); + syslog(LOG_INFO, "restart completed"); + doreset = 0; + errno = oerrno; +#ifdef _POSIX_VERSION + sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0); #else - sigsetmask(omask); + sigsetmask(omask); #endif } @@ -764,40 +678,42 @@ do_reset() static void detach() { - /* detach from terminal and fork. */ - register int i; - register long size; + /* detach from terminal and fork. */ + int i; + long size; -#ifdef POSIX - size = sysconf(_SC_OPEN_MAX); +#ifdef _POSIX_VERSION + size = sysconf(_SC_OPEN_MAX); #else - size = getdtablesize(); -#endif - /* profiling seems to get confused by fork() */ - MONCONTROL (0); - i = fork (); - MONCONTROL (1); - if (i) { - if (i < 0) - perror("fork"); - exit(0); - } + size = getdtablesize(); +#endif + /* profiling seems to get confused by fork() */ + i = fork (); + if (i) { + if (i < 0) + perror("fork"); + exit(0); + } - for (i = 0; i < size; i++) { - (void) close(i); - } - i = open("/dev/tty", O_RDWR, 666); - (void) ioctl(i, TIOCNOTTY, (caddr_t) 0); - (void) close(i); -#ifdef POSIX - (void) setsid(); + for (i = 0; i < size; i++) + close(i); + + i = open("/dev/tty", O_RDWR, 666); +#ifdef TIOCNOTTY /* Only necessary on old systems. */ + ioctl(i, TIOCNOTTY, NULL); #endif -} + close(i); +#ifdef _POSIX_VERSION + setsid(); #endif +} +#endif /* not DEBUG */ static void read_from_dump(dumpfile) - char *dumpfile; + char *dumpfile; { - return; + /* Not yet implemented. */ + return; } + diff --git a/server/main.c.auth b/server/main.c.auth deleted file mode 100644 index c0ae1af..0000000 --- a/server/main.c.auth +++ /dev/null @@ -1,804 +0,0 @@ -/* This file is part of the Project Athena Zephyr Notification System. - * It contains the main loop of the Zephyr server - * - * Created by: John T. Kohl - * - * $Source$ - * $Author$ - * - * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology. - * For copying and distribution information, see the file - * "mit-copyright.h". - */ - -#include <zephyr/mit-copyright.h> - -#ifndef lint -#ifndef SABER -static char rcsid_main_c[] = - "$Id$"; -#endif -#endif - -/* - * Server loop for Zephyr. - */ - -/* - The Zephyr server maintains several linked lists of information. - - There is an array of servers (otherservers) initialized and maintained - by server_s.c. - - Each server descriptor contains a pointer to a linked list of hosts - which are ``owned'' by that server. The first server is the ``limbo'' - server which owns any host which was formerly owned by a dead server. - - Each of these host list entries has an IP address and a pointer to a - linked list of clients on that host. - - Each client has a sockaddr_in, a list of subscriptions, and possibly - a session key. - - In addition, the class manager has copies of the pointers to the - clients which are registered with a particular class, the - not-yet-acknowledged list has copies of pointers to some clients, - and the hostm manager may have copies of pointers to some clients - (if the client has not acknowledged a packet after a given timeout). -*/ - -#include "zserver.h" -/* which includes - zephyr/zephyr.h - <errno.h> - <sys/types.h> - <netinet/in.h> - <sys/time.h> - <stdio.h> - <sys/file.h> - <syslog.h> - <strings.h> - <signal.h> - timer.h - zsrv_err.h - */ - -#include <netdb.h> -#include <sys/socket.h> -#include <sys/param.h> -#include <sys/ioctl.h> -#include <sys/resource.h> -#include <sys/wait.h> -#ifdef POSIX -#include <termios.h> -#endif - -#ifdef POSIX -#define SIGNAL_RETURN_TYPE void -#define SIG_RETURN return -#else -#define SIGNAL_RETURN_TYPE int -#define SIG_RETURN return(0) -#endif - -#if !defined(__SABER__) && (defined (vax) || defined (ibm032)) -#define MONCONTROL moncontrol -#else -#define MONCONTROL (void) -#endif - -#define EVER (;;) /* don't stop looping */ - -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -static int do_net_setup P((void)), initialize P((void)); -static void usage P((void)), do_reset P((void)); -static SIGNAL_RETURN_TYPE bye P((int)), - dbug_on P((int)), dbug_off P((int)), - sig_dump_db P((int)), sig_dump_strings P((int)), - reset P((int)), reap P((int)); -static void read_from_dump P((char *dumpfile)); -static void dump_db P((void)), dump_strings P((void)); - -#ifndef DEBUG -static void detach P((void)); -#endif - -extern void perror P((Zconst char *)); - -#undef P - -static short doreset = 0; /* if it becomes 1, perform - reset functions */ - -int srv_socket; /* dgram socket for clients - and other servers */ -int bdump_socket = -1; /* brain dump socket fd - (closed most of the time) */ -fd_set interesting; /* the file descrips we are listening - to right now */ -int nfildes; /* number to look at in select() */ -struct sockaddr_in sock_sin; /* address of the socket */ -struct timeval nexthost_tv; /* time till next timeout for select */ - -ZNotAcked_t *nacklist; /* list of packets waiting for ack's */ - -u_short hm_port; /* the port # of the host manager */ - -char *programname; /* set to the basename of argv[0] */ -char myname[MAXHOSTNAMELEN]; /* my host name */ - -int zdebug; -#ifdef DEBUG_MALLOC -int dump_malloc_stats = 0; -unsigned long m_size; -#endif -#ifdef DEBUG -int zalone; -#endif - -struct timeval t_local; /* store current time for other uses */ - -static int dump_db_flag = 0; -static int dump_strings_flag = 0; - -u_long npackets; /* number of packets processed */ -long uptime; /* when we started operations */ -static int nofork; -struct in_addr my_addr; -char *bdump_version = "1.1"; - -int -main(argc, argv) - int argc; - char **argv; -{ - int nfound; /* #fildes ready on select */ - fd_set readable; - struct timeval *tvp; - int init_from_dump = 0; - char *dumpfile; -#ifdef POSIX - struct sigaction action; -#endif - - - int optchar; /* option processing */ - extern char *optarg; - extern int optind; - - /* set name */ - if (programname = strrchr(argv[0],'/')) - programname++; - else programname = argv[0]; - - /* process arguments */ - - while ((optchar = getopt(argc, argv, "dsnv:f:")) != EOF) { - switch(optchar) { - case 'd': - zdebug = 1; - break; -#ifdef DEBUG - case 's': - zalone = 1; - break; -#endif - case 'n': - nofork = 1; - break; - case 'v': - bdump_version = optarg; - break; - case 'f': - init_from_dump = 0; - dumpfile = optarg; - break; - case '?': - default: - usage(); - /*NOTREACHED*/ - } - } - -#ifdef KERBEROS - /* if there is no readable srvtab and we are not standalone, there - is no possible way we can succeed, so we exit */ - - if (access(ZEPHYR_SRVTAB, R_OK) -#ifdef DEBUG - && !zalone -#endif /* DEBUG */ - ) { - fprintf(stderr, "NO ZEPHYR SRVTAB (%s) available; exiting\n", - ZEPHYR_SRVTAB); - exit(1); - } -#endif /* KERBEROS */ - -#ifndef DEBUG - if (!nofork) - detach(); -#endif /* DEBUG */ - - /* open log */ - OPENLOG(programname, LOG_PID, LOG_LOCAL6); - -#if defined (DEBUG) && 0 - if (zalone) - syslog(LOG_DEBUG, "standalone operation"); -#endif -#if 0 - if (zdebug) - syslog(LOG_DEBUG, "debugging on"); -#endif - - /* set up sockets & my_addr and myname, - find other servers and set up server table, initialize queues - for retransmits, initialize error tables, - set up restricted classes */ - - /* Initialize t_local for other uses */ - (void) gettimeofday(&t_local, (struct timezone *)0); - - if (initialize()) - exit(1); - - if (init_from_dump) - read_from_dump(dumpfile); - - /* Seed random number set. */ - srandom (getpid () ^ time (0)); - -#ifndef __SABER__ - /* chdir to somewhere where a core dump will survive */ - if (chdir("/usr/tmp") != 0) - syslog(LOG_ERR,"chdir failed (%m) (execution continuing)"); - -#if 0 - /* - * Many systems don't implement setpriority() as is done under BSD, - * and the kernel scheduler will appropriately swap in the processes - * that are needed. - */ - if (setpriority(PRIO_PROCESS, getpid(), -10)) - syslog(LOG_ERR,"setpriority failed (%m)"); -#endif -#endif - - FD_ZERO(&interesting); - FD_SET(srv_socket, &interesting); - - nfildes = srv_socket + 1; - - -#ifdef POSIX - action.sa_flags = 0; - sigemptyset(&action.sa_mask); - - action.sa_handler = bye; - sigaction(SIGINT, &action, NULL); - sigaction(SIGTERM, &action, NULL); - - action.sa_handler = dbug_on; - sigaction(SIGUSR1, &action, NULL); - - action.sa_handler = dbug_off; - sigaction(SIGUSR2, &action, NULL); - - action.sa_handler = reap; - sigaction(SIGCHLD, &action, NULL); - - action.sa_handler = sig_dump_db; - sigaction(SIGFPE, &action, NULL); - sigaction(SIGXCPU, &action, NULL); - -#ifdef SIGEMT - action.sa_handler = sig_dump_strings; - sigaction(SIGEMT, &action, NULL); -#endif - - action.sa_handler = reset; - sigaction(SIGHUP, &action, NULL); -#else /* !posix */ - (void) signal(SIGINT, bye); - (void) signal(SIGTERM, bye); - (void) signal(SIGUSR1, dbug_on); - (void) signal(SIGUSR2, dbug_off); - (void) signal(SIGCHLD, reap); - (void) signal(SIGFPE, sig_dump_db); - (void) signal(SIGXCPU, sig_dump_db); -#ifdef SIGEMT - (void) signal(SIGEMT, sig_dump_strings); -#endif - (void) signal(SIGHUP, reset); -#endif /* POSIX */ - - syslog(LOG_NOTICE, "Ready for action"); - - /* Reinitialize t_local now that initialization is done. */ - (void) gettimeofday(&t_local, (struct timezone *)0); - timer_set_rel(SWEEP_INTERVAL, sweep_ticket_hash_table, NULL); - /* GO! */ - uptime = NOW; - -#ifdef DEBUG_MALLOC - malloc_inuse(&m_size); -#endif - for EVER { - if (doreset) - do_reset(); - - if (dump_db_flag) - dump_db(); - if (dump_strings_flag) - dump_strings(); - - nexthost_tv.tv_usec = 0; - tvp = &nexthost_tv; - - if (nexttimo != 0L) { - nexthost_tv.tv_sec = nexttimo - NOW; - if (nexthost_tv.tv_sec <= 0) { - /* timeout has passed! */ - /* so we process one timeout, then pop to - select, polling for input. This way we get - work done even if swamped with many - timeouts */ - /* this will reset nexttimo */ - (void) timer_process(); - nexthost_tv.tv_sec = 0; - } - } else { /* no timeouts to process */ - nexthost_tv.tv_sec = 15; - } - readable = interesting; - if (msgs_queued()) { - /* when there is input in the queue, we - artificially set up to pick up the input */ - nfound = 1; - FD_ZERO(&readable); - } else - nfound = select(nfildes, &readable, (fd_set *) 0, - (fd_set *) 0, tvp); - - /* Initialize t_local for other uses */ - (void) gettimeofday(&t_local, (struct timezone *)0); - - /* don't flame about EINTR, since a SIGUSR1 or SIGUSR2 - can generate it by interrupting the select */ - if (nfound < 0) { - if (errno != EINTR) - syslog(LOG_WARNING, "select error: %m"); -#ifdef DEBUG_MALLOC - if (dump_malloc_stats) { - unsigned long foo,histid2; - dump_malloc_stats = 0; - foo = malloc_inuse(&histid2); - printf("Total inuse: %d\n",foo); - malloc_list(2,m_size,histid2); - } -#endif - continue; - } - if (nfound == 0) - /* either we timed out or we were just - polling for input. Either way we want to continue - the loop, and process the next timeout */ - continue; - else { - if ((bdump_socket >= 0) && - FD_ISSET(bdump_socket,&readable)) - bdump_send(); - else if (msgs_queued() || - FD_ISSET(srv_socket, &readable)) { - handle_packet(); - } else - syslog(LOG_ERR, "select weird?!?!"); - } - } -} - -/* Initialize net stuff. - Set up the server array. - Initialize the packet ack queues to be empty. - Initialize the error tables. - Restrict certain classes. - */ - -static int -initialize() -{ - if (do_net_setup()) - return(1); - - server_init(); - -#if 0 - if (!(nacklist = (ZNotAcked_t *) xmalloc(sizeof(ZNotAcked_t)))) { - /* unrecoverable */ - syslog(LOG_CRIT, "nacklist malloc"); - abort(); - } -#else - { - static ZNotAcked_t not_acked_head; - nacklist = ¬_acked_head; - } -#endif - (void) memset((caddr_t) nacklist, 0, sizeof(ZNotAcked_t)); - nacklist->q_forw = nacklist->q_back = nacklist; - - nexttimo = 1L; /* trigger the timers when we hit - the FOR loop */ - - (void) ZInitialize(); /* set up the library */ - (void) init_zsrv_err_tbl(); /* set up err table */ - - (void) ZSetServerState(1); - (void) ZSetFD(srv_socket); /* set up the socket as the - input fildes */ - - /* set up default strings */ - - class_control = make_zstring(ZEPHYR_CTL_CLASS, 1); - class_admin = make_zstring(ZEPHYR_ADMIN_CLASS, 1); - class_hm = make_zstring(HM_CTL_CLASS, 1); - class_ulogin = make_zstring(LOGIN_CLASS, 1); - class_ulocate = make_zstring(LOCATE_CLASS, 1); - wildcard_instance = make_zstring(WILDCARD_INSTANCE, 1); - empty = make_zstring("", 0); - - /* restrict certain classes */ - access_init(); - return(0); -} - -/* - * Set up the server and client sockets, and initialize my_addr and myname - */ - -static int -do_net_setup() -{ - struct servent *sp; - struct hostent *hp; - char hostname[MAXHOSTNAMELEN+1]; - int flags; - - if (gethostname(hostname, MAXHOSTNAMELEN+1)) { - syslog(LOG_ERR, "no hostname: %m"); - return(1); - } - if (!(hp = gethostbyname(hostname))) { - syslog(LOG_ERR, "no gethostbyname repsonse"); - (void) strncpy(myname, hostname, MAXHOSTNAMELEN); - return(1); - } - (void) strncpy(myname, hp->h_name, MAXHOSTNAMELEN); - (void) memcpy((caddr_t) &my_addr, (caddr_t) hp->h_addr, - sizeof(hp->h_addr)); - - (void) setservent(1); /* keep file/connection open */ - - if (!(sp = getservbyname(SERVER_SVCNAME, "udp"))) { - syslog(LOG_ERR, "%s/udp unknown",SERVER_SVCNAME); - return(1); - } - (void) memset((caddr_t) &sock_sin, 0, sizeof(sock_sin)); - sock_sin.sin_port = sp->s_port; - - if (!(sp = getservbyname(HM_SVCNAME, "udp"))) { - syslog(LOG_ERR, "%s/udp unknown", HM_SVCNAME); - return(1); - } - hm_port = sp->s_port; - - (void) endservent(); - - if ((srv_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - syslog(LOG_ERR, "client_sock failed: %m"); - return(1); - } - if (bind(srv_socket, (struct sockaddr *) &sock_sin, - sizeof(sock_sin)) < 0) { - syslog(LOG_ERR, "client bind failed: %m"); - return(1); - } - - /* set not-blocking */ -#ifdef POSIX - flags = fcntl(srv_socket, F_GETFL); - flags |= O_NONBLOCK; - (void) fcntl(srv_socket, F_SETFL, flags); -#else - flags = 1; - (void) ioctl(srv_socket, FIONBIO, (caddr_t) &flags); -#endif - - return(0); -} - - -/* - * print out a usage message. - */ - -static void -usage() -{ -#ifdef DEBUG - fprintf(stderr,"Usage: %s [-d] [-s] [-n] [-f dumpfile]\n",programname); -#else - fprintf(stderr,"Usage: %s [-d] [-n] [-f dumpfile]\n",programname); -#endif /* DEBUG */ - exit(2); -} - -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -bye(int sig) -#else -bye(sig) - int sig; -#endif -{ - server_shutdown(); /* tell other servers */ - hostm_shutdown(); /* tell our hosts */ -#ifdef KERBEROS - (void) dest_tkt(); -#endif - syslog(LOG_NOTICE, "goodbye (sig %d)",sig); - exit(0); - /*NOTREACHED*/ -} - -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -dbug_on(int sig) -#else -dbug_on(sig) - int sig; -#endif -{ - syslog(LOG_DEBUG, "debugging turned on"); -#ifdef DEBUG_MALLOC - dump_malloc_stats = 1; -#endif - zdebug = 1; - SIG_RETURN; -} - -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -dbug_off(int sig) -#else -dbug_off(sig) - int sig; -#endif -{ - syslog(LOG_DEBUG, "debugging turned off"); -#ifdef DEBUG_MALLOC - malloc_inuse(&m_size); -#endif - zdebug = 0; - SIG_RETURN; -} - -int fork_for_dump = 0; - -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -sig_dump_strings (int sig) -#else -sig_dump_strings(sig) - int sig; -#endif -{ - dump_strings_flag = 1; - SIG_RETURN; -} - -static void dump_strings() -{ - FILE *fp; - int oerrno = errno; - fp = fopen ("/usr/tmp/zephyr.strings", "w"); - if (!fp) { - syslog (LOG_ERR, "can't open strings dump file: %m"); - errno = oerrno; - dump_strings_flag = 0; - return; - } - syslog (LOG_INFO, "dumping strings to disk"); - print_zstring_table(fp); - if (fclose (fp) == EOF) - syslog (LOG_ERR, "error writing strings dump file"); - else - syslog (LOG_INFO, "dump done"); - oerrno = errno; - dump_strings_flag = 0; - return; -} - -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -sig_dump_db(int sig) -#else -sig_dump_db(sig) - int sig; -#endif -{ - dump_db_flag = 1; - SIG_RETURN; -} - -static void dump_db() -{ - /* dump the in-core database to human-readable form on disk */ - FILE *fp; - int oerrno = errno; - int pid; - -#ifdef __SABER__ - pid = -1; -#else - if (fork_for_dump) { - MONCONTROL (0); - pid = fork (); - MONCONTROL (1); - } - else - pid = -1; -#endif - if (pid > 0) - { - dump_db_flag = 0; - return; - } - if ((fp = fopen("/usr/tmp/zephyr.db", "w")) == (FILE *)0) { - syslog(LOG_ERR, "can't open dump database"); - errno = oerrno; - dump_db_flag = 0; - return; - } - syslog(LOG_INFO, "dumping to disk"); - server_dump_servers(fp); - uloc_dump_locs(fp); - hostm_dump_hosts(fp); - class_dump_subs(fp); - syslog(LOG_INFO, "dump done"); - if (fclose(fp) == EOF) { - syslog(LOG_ERR, "can't close dump db"); - } - if (pid == 0) - exit (0); - errno = oerrno; - dump_db_flag = 0; - return; -} - -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -reset(int sig) -#else -reset(sig) - int sig; -#endif -{ -#if 1 - zdbug((LOG_DEBUG,"reset()")); -#endif - doreset = 1; - SIG_RETURN; -} - -#ifdef __GNUG__ -#define wait WaitStatus -#endif - -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -reap(int sig) -#else -reap(sig) - int sig; -#endif -{ - int oerrno = errno; - -#ifdef POSIX - int waitb; - while (waitpid(-1, &waitb, WNOHANG) == 0) ; -#else - union wait waitb; - while (wait3 (&waitb, WNOHANG, (struct rusage*) 0) == 0) ; -#endif - - errno = oerrno; - SIG_RETURN; -} - -static void -do_reset() -{ - int oerrno = errno; -#ifdef POSIX - sigset_t mask, omask; -#else - int omask; -#endif -#if 0 - zdbug((LOG_DEBUG,"do_reset()")); -#endif -#ifdef POSIX - sigemptyset(&mask); - sigaddset(&mask, SIGHUP); - sigprocmask(SIG_BLOCK, &mask, &omask); -#else - omask = sigblock(sigmask(SIGHUP)); -#endif - - /* reset various things in the server's state */ - subscr_reset(); - server_reset(); - access_reinit(); - syslog (LOG_INFO, "restart completed"); - doreset = 0; - errno = oerrno; -#ifdef POSIX - sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0); -#else - sigsetmask(omask); -#endif -} - -#ifndef DEBUG -/* - * detach from the terminal - */ - -static void -detach() -{ - /* detach from terminal and fork. */ - register int i; - register long size; - -#ifdef POSIX - size = sysconf(_SC_OPEN_MAX); -#else - size = getdtablesize(); -#endif - /* profiling seems to get confused by fork() */ - MONCONTROL (0); - i = fork (); - MONCONTROL (1); - if (i) { - if (i < 0) - perror("fork"); - exit(0); - } - - for (i = 0; i < size; i++) { - (void) close(i); - } - i = open("/dev/tty", O_RDWR, 666); - (void) ioctl(i, TIOCNOTTY, (caddr_t) 0); - (void) close(i); -#ifdef POSIX - (void) setsid(); -#endif -} -#endif - -static void -read_from_dump(dumpfile) - char *dumpfile; -{ - return; -} diff --git a/server/main.c.old b/server/main.c.old deleted file mode 100644 index b3ec4e4..0000000 --- a/server/main.c.old +++ /dev/null @@ -1,803 +0,0 @@ -/* This file is part of the Project Athena Zephyr Notification System. - * It contains the main loop of the Zephyr server - * - * Created by: John T. Kohl - * - * $Source$ - * $Author$ - * - * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology. - * For copying and distribution information, see the file - * "mit-copyright.h". - */ - -#include <zephyr/mit-copyright.h> - -#ifndef lint -#ifndef SABER -static char rcsid_main_c[] = - "$Id$"; -#endif -#endif - -/* - * Server loop for Zephyr. - */ - -/* - The Zephyr server maintains several linked lists of information. - - There is an array of servers (otherservers) initialized and maintained - by server_s.c. - - Each server descriptor contains a pointer to a linked list of hosts - which are ``owned'' by that server. The first server is the ``limbo'' - server which owns any host which was formerly owned by a dead server. - - Each of these host list entries has an IP address and a pointer to a - linked list of clients on that host. - - Each client has a sockaddr_in, a list of subscriptions, and possibly - a session key. - - In addition, the class manager has copies of the pointers to the - clients which are registered with a particular class, the - not-yet-acknowledged list has copies of pointers to some clients, - and the hostm manager may have copies of pointers to some clients - (if the client has not acknowledged a packet after a given timeout). -*/ - -#include "zserver.h" -/* which includes - zephyr/zephyr.h - <errno.h> - <sys/types.h> - <netinet/in.h> - <sys/time.h> - <stdio.h> - <sys/file.h> - <syslog.h> - <strings.h> - <signal.h> - timer.h - zsrv_err.h - */ - -#include <netdb.h> -#include <sys/socket.h> -#include <sys/param.h> -#include <sys/ioctl.h> -#include <sys/resource.h> -#include <sys/wait.h> -#ifdef POSIX -#include <termios.h> -#endif - -#ifdef POSIX -#define SIGNAL_RETURN_TYPE void -#define SIG_RETURN return -#else -#define SIGNAL_RETURN_TYPE int -#define SIG_RETURN return(0) -#endif - -#if !defined(__SABER__) && (defined (vax) || defined (ibm032)) -#define MONCONTROL moncontrol -#else -#define MONCONTROL (void) -#endif - -#define EVER (;;) /* don't stop looping */ - -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -static int do_net_setup P((void)), initialize P((void)); -static void usage P((void)), do_reset P((void)); -static SIGNAL_RETURN_TYPE bye P((int)), - dbug_on P((int)), dbug_off P((int)), - sig_dump_db P((int)), sig_dump_strings P((int)), - reset P((int)), reap P((int)); -static void read_from_dump P((char *dumpfile)); -static void dump_db P((void)), dump_strings P((void)); - -#ifndef DEBUG -static void detach P((void)); -#endif - -extern void perror P((Zconst char *)); - -#undef P - -static short doreset = 0; /* if it becomes 1, perform - reset functions */ - -int srv_socket; /* dgram socket for clients - and other servers */ -int bdump_socket = -1; /* brain dump socket fd - (closed most of the time) */ -fd_set interesting; /* the file descrips we are listening - to right now */ -int nfildes; /* number to look at in select() */ -struct sockaddr_in sock_sin; /* address of the socket */ -struct timeval nexthost_tv; /* time till next timeout for select */ - -ZNotAcked_t *nacklist; /* list of packets waiting for ack's */ - -u_short hm_port; /* the port # of the host manager */ - -char *programname; /* set to the basename of argv[0] */ -char myname[MAXHOSTNAMELEN]; /* my host name */ - -int zdebug; -#ifdef DEBUG_MALLOC -int dump_malloc_stats = 0; -unsigned long m_size; -#endif -#ifdef DEBUG -int zalone; -#endif - -struct timeval t_local; /* store current time for other uses */ - -static int dump_db_flag = 0; -static int dump_strings_flag = 0; - -u_long npackets; /* number of packets processed */ -long uptime; /* when we started operations */ -static int nofork; -struct in_addr my_addr; -char *bdump_version = "1.1"; - -int -main(argc, argv) - int argc; - char **argv; -{ - int nfound; /* #fildes ready on select */ - fd_set readable; - struct timeval *tvp; - int init_from_dump = 0; - char *dumpfile; -#ifdef POSIX - struct sigaction action; -#endif - - - int optchar; /* option processing */ - extern char *optarg; - extern int optind; - - /* set name */ - if (programname = strrchr(argv[0],'/')) - programname++; - else programname = argv[0]; - - /* process arguments */ - - while ((optchar = getopt(argc, argv, "dsnv:f:")) != EOF) { - switch(optchar) { - case 'd': - zdebug = 1; - break; -#ifdef DEBUG - case 's': - zalone = 1; - break; -#endif - case 'n': - nofork = 1; - break; - case 'v': - bdump_version = optarg; - break; - case 'f': - init_from_dump = 0; - dumpfile = optarg; - break; - case '?': - default: - usage(); - /*NOTREACHED*/ - } - } - -#ifdef KERBEROS - /* if there is no readable srvtab and we are not standalone, there - is no possible way we can succeed, so we exit */ - - if (access(ZEPHYR_SRVTAB, R_OK) -#ifdef DEBUG - && !zalone -#endif /* DEBUG */ - ) { - fprintf(stderr, "NO ZEPHYR SRVTAB (%s) available; exiting\n", - ZEPHYR_SRVTAB); - exit(1); - } -#endif /* KERBEROS */ - -#ifndef DEBUG - if (!nofork) - detach(); -#endif /* DEBUG */ - - /* open log */ - OPENLOG(programname, LOG_PID, LOG_LOCAL6); - -#if defined (DEBUG) && 0 - if (zalone) - syslog(LOG_DEBUG, "standalone operation"); -#endif -#if 0 - if (zdebug) - syslog(LOG_DEBUG, "debugging on"); -#endif - - /* set up sockets & my_addr and myname, - find other servers and set up server table, initialize queues - for retransmits, initialize error tables, - set up restricted classes */ - - if (initialize()) - exit(1); - - if (init_from_dump) - read_from_dump(dumpfile); - - /* Seed random number set. */ - srandom (getpid () ^ time (0)); - -#ifndef __SABER__ - /* chdir to somewhere where a core dump will survive */ - if (chdir("/usr/tmp") != 0) - syslog(LOG_ERR,"chdir failed (%m) (execution continuing)"); - -#if 0 - /* - * Many systems don't implement setpriority() as is done under BSD, - * and the kernel scheduler will appropriately swap in the processes - * that are needed. - */ - if (setpriority(PRIO_PROCESS, getpid(), -10)) - syslog(LOG_ERR,"setpriority failed (%m)"); -#endif -#endif - - FD_ZERO(&interesting); - FD_SET(srv_socket, &interesting); - - nfildes = srv_socket + 1; - - -#ifdef POSIX - action.sa_flags = 0; - sigemptyset(&action.sa_mask); - - action.sa_handler = bye; - sigaction(SIGINT, &action, NULL); - sigaction(SIGTERM, &action, NULL); - - action.sa_handler = dbug_on; - sigaction(SIGUSR1, &action, NULL); - - action.sa_handler = dbug_off; - sigaction(SIGUSR2, &action, NULL); - - action.sa_handler = reap; - sigaction(SIGCHLD, &action, NULL); - - action.sa_handler = sig_dump_db; - sigaction(SIGFPE, &action, NULL); - sigaction(SIGXCPU, &action, NULL); - - action.sa_handler = sig_dump_strings; - sigaction(SIGEMT, &action, NULL); - - action.sa_handler = reset; - sigaction(SIGHUP, &action, NULL); -#else /* !posix */ - (void) signal(SIGINT, bye); - (void) signal(SIGTERM, bye); - (void) signal(SIGUSR1, dbug_on); - (void) signal(SIGUSR2, dbug_off); - (void) signal(SIGCHLD, reap); - (void) signal(SIGFPE, sig_dump_db); - (void) signal(SIGXCPU, sig_dump_db); - (void) signal(SIGEMT, sig_dump_strings); - (void) signal(SIGHUP, reset); -#endif /* POSIX */ - - syslog(LOG_NOTICE, "Ready for action"); - - /* Initialize t_local for other uses */ - (void) gettimeofday(&t_local, (struct timezone *)0); - /* GO! */ - uptime = NOW; - -#ifdef DEBUG_MALLOC - malloc_inuse(&m_size); -#endif - for EVER { - if (doreset) - do_reset(); - - if (dump_db_flag) - dump_db(); - if (dump_strings_flag) - dump_strings(); - - nexthost_tv.tv_usec = 0; - tvp = &nexthost_tv; - - if (nexttimo != 0L) { - nexthost_tv.tv_sec = nexttimo - NOW; - if (nexthost_tv.tv_sec <= 0) { - /* timeout has passed! */ - /* so we process one timeout, then pop to - select, polling for input. This way we get - work done even if swamped with many - timeouts */ - /* this will reset nexttimo */ - (void) timer_process(); - nexthost_tv.tv_sec = 0; - } - } else { /* no timeouts to process */ - nexthost_tv.tv_sec = 15; - } - readable = interesting; - if (msgs_queued()) { - /* when there is input in the queue, we - artificially set up to pick up the input */ - nfound = 1; - FD_ZERO(&readable); - } else - nfound = select(nfildes, &readable, (fd_set *) 0, - (fd_set *) 0, tvp); - - /* Initialize t_local for other uses */ - (void) gettimeofday(&t_local, (struct timezone *)0); - - /* don't flame about EINTR, since a SIGUSR1 or SIGUSR2 - can generate it by interrupting the select */ - if (nfound < 0) { - if (errno != EINTR) - syslog(LOG_WARNING, "select error: %m"); -#ifdef DEBUG_MALLOC - if (dump_malloc_stats) { - unsigned long foo,histid2; - dump_malloc_stats = 0; - foo = malloc_inuse(&histid2); - printf("Total inuse: %d\n",foo); - malloc_list(2,m_size,histid2); - } -#endif - continue; - } - if (nfound == 0) - /* either we timed out or we were just - polling for input. Either way we want to continue - the loop, and process the next timeout */ - continue; - else { - if ((bdump_socket >= 0) && - FD_ISSET(bdump_socket,&readable)) - bdump_send(); - else if (msgs_queued() || - FD_ISSET(srv_socket, &readable)) { - handle_packet(); - } else - syslog(LOG_ERR, "select weird?!?!"); - } - } -} - -/* Initialize net stuff. - Set up the server array. - Initialize the packet ack queues to be empty. - Initialize the error tables. - Restrict certain classes. - */ - -static int -initialize() -{ - if (do_net_setup()) - return(1); - - server_init(); - -#if 0 - if (!(nacklist = (ZNotAcked_t *) xmalloc(sizeof(ZNotAcked_t)))) { - /* unrecoverable */ - syslog(LOG_CRIT, "nacklist malloc"); - abort(); - } -#else - { - static ZNotAcked_t not_acked_head; - nacklist = ¬_acked_head; - } -#endif - (void) memset((caddr_t) nacklist, 0, sizeof(ZNotAcked_t)); - nacklist->q_forw = nacklist->q_back = nacklist; - - nexttimo = 1L; /* trigger the timers when we hit - the FOR loop */ - - (void) ZInitialize(); /* set up the library */ - (void) init_zsrv_err_tbl(); /* set up err table */ - - (void) ZSetServerState(1); - (void) ZSetFD(srv_socket); /* set up the socket as the - input fildes */ - - /* set up default strings */ - - class_control = make_zstring(ZEPHYR_CTL_CLASS, 1); - class_admin = make_zstring(ZEPHYR_ADMIN_CLASS, 1); - class_hm = make_zstring(HM_CTL_CLASS, 1); - class_ulogin = make_zstring(LOGIN_CLASS, 1); - class_ulocate = make_zstring(LOCATE_CLASS, 1); - wildcard_class = make_zstring(MATCHALL_CLASS, 1); - wildcard_instance = make_zstring(WILDCARD_INSTANCE, 1); - empty = make_zstring("", 0); - - matchall_sub.q_forw = &matchall_sub; - matchall_sub.q_back = &matchall_sub; - matchall_sub.zst_dest.classname = wildcard_class; - matchall_sub.zst_dest.inst = dup_zstring(empty); - matchall_sub.zst_dest.recip = dup_zstring(empty); - - set_ZDestination_hash(&matchall_sub.zst_dest); - /* restrict certain classes */ - access_init(); - return(0); -} - -/* - * Set up the server and client sockets, and initialize my_addr and myname - */ - -static int -do_net_setup() -{ - struct servent *sp; - struct hostent *hp; - char hostname[MAXHOSTNAMELEN+1]; - int flags; - - if (gethostname(hostname, MAXHOSTNAMELEN+1)) { - syslog(LOG_ERR, "no hostname: %m"); - return(1); - } - if (!(hp = gethostbyname(hostname))) { - syslog(LOG_ERR, "no gethostbyname repsonse"); - (void) strncpy(myname, hostname, MAXHOSTNAMELEN); - return(1); - } - (void) strncpy(myname, hp->h_name, MAXHOSTNAMELEN); - (void) memcpy((caddr_t) &my_addr, (caddr_t) hp->h_addr, - sizeof(hp->h_addr)); - - (void) setservent(1); /* keep file/connection open */ - - if (!(sp = getservbyname(SERVER_SVCNAME, "udp"))) { - syslog(LOG_ERR, "%s/udp unknown",SERVER_SVCNAME); - return(1); - } - (void) memset((caddr_t) &sock_sin, 0, sizeof(sock_sin)); - sock_sin.sin_port = sp->s_port; - - if (!(sp = getservbyname(HM_SVCNAME, "udp"))) { - syslog(LOG_ERR, "%s/udp unknown", HM_SVCNAME); - return(1); - } - hm_port = sp->s_port; - - (void) endservent(); - - if ((srv_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - syslog(LOG_ERR, "client_sock failed: %m"); - return(1); - } - if (bind(srv_socket, (struct sockaddr *) &sock_sin, - sizeof(sock_sin)) < 0) { - syslog(LOG_ERR, "client bind failed: %m"); - return(1); - } - - /* set not-blocking */ -#ifdef POSIX - flags = fcntl(srv_socket, F_GETFL); - flags |= O_NONBLOCK; - (void) fcntl(srv_socket, F_SETFL, flags); -#else - flags = 1; - (void) ioctl(srv_socket, FIONBIO, (caddr_t) &flags); -#endif - - return(0); -} - - -/* - * print out a usage message. - */ - -static void -usage() -{ -#ifdef DEBUG - fprintf(stderr,"Usage: %s [-d] [-s] [-n] [-f dumpfile]\n",programname); -#else - fprintf(stderr,"Usage: %s [-d] [-n] [-f dumpfile]\n",programname); -#endif /* DEBUG */ - exit(2); -} - -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -bye(int sig) -#else -bye(sig) - int sig; -#endif -{ - server_shutdown(); /* tell other servers */ - hostm_shutdown(); /* tell our hosts */ -#ifdef KERBEROS - (void) dest_tkt(); -#endif - syslog(LOG_NOTICE, "goodbye (sig %d)",sig); - exit(0); - /*NOTREACHED*/ -} - -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -dbug_on(int sig) -#else -dbug_on(sig) - int sig; -#endif -{ - syslog(LOG_DEBUG, "debugging turned on"); -#ifdef DEBUG_MALLOC - dump_malloc_stats = 1; -#endif - zdebug = 1; - SIG_RETURN; -} - -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -dbug_off(int sig) -#else -dbug_off(sig) - int sig; -#endif -{ - syslog(LOG_DEBUG, "debugging turned off"); -#ifdef DEBUG_MALLOC - malloc_inuse(&m_size); -#endif - zdebug = 0; - SIG_RETURN; -} - -int fork_for_dump = 0; - -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -sig_dump_strings (int sig) -#else -sig_dump_strings(sig) - int sig; -#endif -{ - dump_strings_flag = 1; - SIG_RETURN; -} - -static void dump_strings() -{ - FILE *fp; - int oerrno = errno; - fp = fopen ("/usr/tmp/zephyr.strings", "w"); - if (!fp) { - syslog (LOG_ERR, "can't open strings dump file: %m"); - errno = oerrno; - dump_strings_flag = 0; - return; - } - syslog (LOG_INFO, "dumping strings to disk"); - print_zstring_table(fp); - if (fclose (fp) == EOF) - syslog (LOG_ERR, "error writing strings dump file"); - else - syslog (LOG_INFO, "dump done"); - oerrno = errno; - dump_strings_flag = 0; - return; -} - -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -sig_dump_db(int sig) -#else -sig_dump_db(sig) - int sig; -#endif -{ - dump_db_flag = 1; - SIG_RETURN; -} - -static void dump_db() -{ - /* dump the in-core database to human-readable form on disk */ - FILE *fp; - int oerrno = errno; - int pid; - -#ifdef __SABER__ - pid = -1; -#else - if (fork_for_dump) { - MONCONTROL (0); - pid = fork (); - MONCONTROL (1); - } - else - pid = -1; -#endif - if (pid > 0) - { - dump_db_flag = 0; - return; - } - if ((fp = fopen("/usr/tmp/zephyr.db", "w")) == (FILE *)0) { - syslog(LOG_ERR, "can't open dump database"); - errno = oerrno; - dump_db_flag = 0; - return; - } - syslog(LOG_INFO, "dumping to disk"); - server_dump_servers(fp); - uloc_dump_locs(fp); - hostm_dump_hosts(fp); - syslog(LOG_INFO, "dump done"); - if (fclose(fp) == EOF) { - syslog(LOG_ERR, "can't close dump db"); - } - if (pid == 0) - exit (0); - errno = oerrno; - dump_db_flag = 0; - return; -} - -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -reset(int sig) -#else -reset(sig) - int sig; -#endif -{ -#if 1 - zdbug((LOG_DEBUG,"reset()")); -#endif - doreset = 1; - SIG_RETURN; -} - -#ifdef __GNUG__ -#define wait WaitStatus -#endif - -static SIGNAL_RETURN_TYPE -#ifdef __STDC__ -reap(int sig) -#else -reap(sig) - int sig; -#endif -{ - int oerrno = errno; - -#ifdef POSIX - int waitb; - while (waitpid(-1, &waitb, WNOHANG) == 0) ; -#else - union wait waitb; - while (wait3 (&waitb, WNOHANG, (struct rusage*) 0) == 0) ; -#endif - - errno = oerrno; - SIG_RETURN; -} - -static void -do_reset() -{ - int oerrno = errno; -#ifdef POSIX - sigset_t mask, omask; -#else - int omask; -#endif -#if 0 - zdbug((LOG_DEBUG,"do_reset()")); -#endif -#ifdef POSIX - sigemptyset(&mask); - sigaddset(&mask, SIGHUP); - sigprocmask(SIG_BLOCK, &mask, &omask); -#else - omask = sigblock(sigmask(SIGHUP)); -#endif - - /* reset various things in the server's state */ - subscr_reset(); - server_reset(); - access_reinit(); - syslog (LOG_INFO, "restart completed"); - doreset = 0; - errno = oerrno; -#ifdef POSIX - sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0); -#else - sigsetmask(omask); -#endif -} - -#ifndef DEBUG -/* - * detach from the terminal - */ - -static void -detach() -{ - /* detach from terminal and fork. */ - register int i; - register long size; - -#ifdef POSIX - size = sysconf(_SC_OPEN_MAX); -#else - size = getdtablesize(); -#endif - /* profiling seems to get confused by fork() */ - MONCONTROL (0); - i = fork (); - MONCONTROL (1); - if (i) { - if (i < 0) - perror("fork"); - exit(0); - } - - for (i = 0; i < size; i++) { - (void) close(i); - } - i = open("/dev/tty", O_RDWR, 666); - (void) ioctl(i, TIOCNOTTY, (caddr_t) 0); - (void) close(i); -#ifdef POSIX - (void) setsid(); -#endif -} -#endif - -static void -read_from_dump(dumpfile) - char *dumpfile; -{ - return; -} diff --git a/server/realm.c b/server/realm.c new file mode 100644 index 0000000..de2dc12 --- /dev/null +++ b/server/realm.c @@ -0,0 +1,1086 @@ +#include "zserver.h" +#include <sys/socket.h> + +extern int __My_length; +extern char *__My_addr; + +Unacked *rlm_nacklist = NULL; /* not acked list for realm-realm + packets */ +Realm *otherrealms; /* points to an array of the known + servers */ +int nrealms = 0; /* number of other realms */ + +static void get_realm_addrs __P(()); +static void realm_sendit __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, Realm *realm, int ack_to_sender)); +static void realm_sendit_auth __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, Realm *realm, int ack_to_sender)); +static void rlm_ack __P((ZNotice_t *notice, Unacked *nacked)); +static void rlm_nack_cancel __P((ZNotice_t *notice, struct sockaddr_in *who)); +static void rlm_new_ticket __P(()); +static void rlm_rexmit __P((void *arg)); +static Code_t realm_ulocate_dispatch __P((ZNotice_t *notice,int auth,struct sockaddr_in *who,Server *server,Realm *realm)); +#ifdef ZEPHYR_USES_KERBEROS +static Code_t ticket_retrieve __P((Realm *realm)); +#endif + +char * +realm_expand_realm(realmname) +char *realmname; +{ + static char expand[REALM_SZ]; + static char krb_realm[REALM_SZ+1]; + char *cp1, *cp2; + int retval; + FILE *rlm_file; + char list_file[128]; + char linebuf[BUFSIZ]; + char scratch[128]; + + /* upcase what we got */ + cp2 = realmname; + cp1 = expand; + while (*cp2) { + *cp1++ = toupper(*cp2++); + } + *cp1 = '\0'; + + sprintf(list_file, "%s/%s", CONFDIR, REALM_LIST_FILE); + + if ((rlm_file = fopen(list_file, "r")) == (FILE *) 0) { + return(expand); + } + + if (fgets(linebuf, BUFSIZ, rlm_file) == NULL) { + /* error reading */ + (void) fclose(rlm_file); + return(expand); + } + + while (1) { + /* run through the file, looking for admin host */ + if (fgets(linebuf, BUFSIZ, rlm_file) == NULL) { + (void) fclose(rlm_file); + return(expand); + } + + if (sscanf(linebuf, "%s %s", krb_realm, scratch) < 2) + continue; + if (!strncmp(krb_realm, expand, strlen(expand))) { + (void) fclose(rlm_file); + return(krb_realm); + } + } +#ifdef KERBEROS + if (!strncmp(my_realm, expand, strlen(expand))) + return(my_realm); +#endif + return(expand); +} + +Realmname * +get_realm_lists(file) + char *file; +{ + Realmname *rlm_list, *rlm; + int ii, nused, ntotal; + FILE *fp; + char buf[REALM_SZ + MAXHOSTNAMELEN + 1]; /* one for newline */ + char realm[REALM_SZ], server[MAXHOSTNAMELEN + 1]; + + nused = 0; + if (!(fp = fopen(file, "r"))) + return((Realmname *)0); + + /* start with 16, realloc if necessary */ + ntotal = 16; + rlm_list = (Realmname *)malloc(ntotal * sizeof(Realmname)); + if (!rlm_list) { + syslog(LOG_CRIT, "get_realm_lists malloc"); + abort(); + } + + while (fgets(buf, REALM_SZ + MAXHOSTNAMELEN + 1, fp)) { + if (sscanf(buf, "%s %s", realm, server) != 2) { + syslog(LOG_CRIT, "bad format in %s", file); + abort(); + } + for (ii = 0; ii < nused; ii++) { + /* look for this realm */ + if (!strcmp(rlm_list[ii].name, realm)) + break; + } + if (ii < nused) { + rlm = &rlm_list[ii]; + if (rlm->nused +1 >= rlm->nservers) { + /* make more space */ + rlm->servers = (char **)realloc((char *)rlm->servers, + (unsigned)rlm->nservers * 2 * + sizeof(char *)); + if (!rlm->servers) { + syslog(LOG_CRIT, "get_realm_lists realloc"); + abort(); + } + rlm->nservers *= 2; + } + rlm->servers[rlm->nused++] = strsave(server); + } else { + /* new realm */ + if (nused + 1 >= ntotal) { + /* make more space */ + rlm_list = (Realmname *)realloc((char *)rlm_list, + (unsigned)ntotal * 2 * + sizeof(Realmname)); + if (!rlm_list) { + syslog(LOG_CRIT, "get_realm_lists realloc"); + abort(); + } + ntotal *= 2; + } + rlm = &rlm_list[nused++]; + strcpy(rlm->name, realm); + rlm->nused = 0; + rlm->nservers = 16; + rlm->servers = (char **)malloc(rlm->nservers * sizeof(char *)); + if (!rlm->servers) { + syslog(LOG_CRIT, "get_realm_lists malloc"); + abort(); + } + rlm->servers[rlm->nused++] = strsave(server); + } + } + if (nused + 1 >= ntotal) { + rlm_list = (Realmname *)realloc((char *)rlm_list, + (unsigned)(ntotal + 1) * + sizeof(Realmname)); + if (!rlm_list) { + syslog(LOG_CRIT, "get_realm_lists realloc"); + abort(); + } + } + *rlm_list[nused].name = '\0'; + + return(rlm_list); +} + +Code_t +realm_send_realms() +{ + int cnt, retval; + for (cnt = 0; cnt < nrealms; cnt++) { + if (retval = (subscr_send_realm_subs(&otherrealms[cnt])) != ZERR_NONE) + return(retval); + } +} + +int +bound_for_local_realm(notice) + ZNotice_t *notice; +{ + char *realm; + + realm = strchr(notice->z_recipient, '@'); + + if (!realm || !strcmp(realm_expand_realm(realm + 1), ZGetRealm())) + return 1; + + return 0; +} + +int +sender_in_realm(notice) + ZNotice_t *notice; +{ + char *realm; + + realm = strchr(notice->z_sender, '@'); + + if (!realm || !strcmp(realm + 1, ZGetRealm())) + return 1; + + return 0; +} + +Realm * +realm_which_realm(who) + struct sockaddr_in *who; +{ + Realm *realm; + struct sockaddr_in *addr; + int a, b; + + /* loop through the realms */ + for (realm = otherrealms, a = 0; a < nrealms; a++, realm++) + /* loop through the addresses for the realm */ + for (addr = realm->addrs, b = 0; b < realm->count; b++, addr++) + if (addr->sin_addr.s_addr == who->sin_addr.s_addr) + return(realm); + + return 0; +} + +Realm * +realm_get_realm_by_name(name) +char *name; +{ + int a; + Realm *realm; + + for (realm = otherrealms, a = 0; a < nrealms; a++, realm++) + if (!strcmp(realm->name, name)) + return(realm); + + return 0; +} + +static void +rlm_nack_cancel(notice, who) + register ZNotice_t *notice; + struct sockaddr_in *who; +{ + register Realm *which = realm_which_realm(who); + register Unacked *nacked, *next; + ZNotice_t acknotice; + ZPacket_t retval; + +#if 0 + zdbug((LOG_DEBUG, "rlm_nack_cancel: %s:%08X,%08X", + inet_ntoa(notice->z_uid.zuid_addr), + notice->z_uid.tv.tv_sec, notice->z_uid.tv.tv_usec)); +#endif + if (!which) { + syslog(LOG_ERR, "non-realm ack?"); + return; + } + + for (nacked = rlm_nacklist; nacked; nacked = nacked->next) { + if (&otherrealms[nacked->dest.rlm.rlm_idx] == which) { + if (ZCompareUID(&nacked->uid, ¬ice->z_uid)) { + timer_reset(nacked->timer); + + if (nacked->ack_addr.sin_addr.s_addr) + rlm_ack(notice, nacked); + + /* free the data */ + free(nacked->packet); + LIST_DELETE(nacked); + free(nacked); + return; + } + } + } +#if 0 + zdbug((LOG_DEBUG,"nack_cancel: nack not found %s:%08X,%08X", + inet_ntoa (notice->z_uid.zuid_addr), + notice->z_uid.tv.tv_sec, notice->z_uid.tv.tv_usec)); +#endif + return; +} + +static void +rlm_ack(notice, nacked) + ZNotice_t *notice; + Unacked *nacked; +{ + ZNotice_t acknotice; + ZPacket_t ackpack; + int packlen; + Code_t retval; + + /* tell the original sender the result */ + acknotice = *notice; + acknotice.z_message_len = strlen(acknotice.z_message) + 1; + + packlen = sizeof(ackpack); + + if ((retval = ZFormatSmallRawNotice(&acknotice, ackpack, &packlen)) != ZERR_NONE) { + syslog(LOG_ERR, "rlm_ack format: %s", + error_message(retval)); + return; + } + zdbug((LOG_DEBUG, "rlm_ack sending to %s/%d", + inet_ntoa(nacked->ack_addr.sin_addr), + ntohs(nacked->ack_addr.sin_port))); + if ((retval = ZSetDestAddr(&nacked->ack_addr)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_ack set addr: %s", + error_message(retval)); + return; + } + if ((retval = ZSendPacket(ackpack, packlen, 0)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_ack xmit: %s", error_message(retval)); + return; + } +} + + +Code_t +realm_dispatch(notice, auth, who, server) + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + Server *server; +{ + Realm *realm; + struct sockaddr_in newwho; + Code_t status = ZERR_NONE; + char rlm_recipient[REALM_SZ + 1]; + int external = 0; + String *notice_class; + + if (notice->z_kind == SERVACK || notice->z_kind == SERVNAK) { + rlm_nack_cancel(notice, who); + return(ZERR_NONE); + } + /* set up a who for the real origin */ + memset((caddr_t) &newwho, 0, sizeof(newwho)); + newwho.sin_family = AF_INET; + newwho.sin_addr.s_addr = notice->z_sender_addr.s_addr; + newwho.sin_port = hm_port; + + /* check if it's a control message */ + realm = realm_which_realm(who); + + notice_class = make_string(notice->z_class,1); + + if (class_is_admin(notice_class)) { + syslog(LOG_WARNING, "%s sending admin opcode %s", + realm->name, notice->z_opcode); + } else if (class_is_hm(notice_class)) { + syslog(LOG_WARNING, "%s sending hm opcode %s", + realm->name, notice->z_opcode); + } else if (class_is_control(notice_class)) { + status = realm_control_dispatch(notice, auth, who, + server, realm); + } else if (class_is_ulogin(notice_class)) { + /* don't need to forward this */ + if (server == me_server) { + sprintf(rlm_recipient, "@%s", realm->name); + notice->z_recipient = rlm_recipient; + + sendit(notice, 1, who, 0); + } + } else if (class_is_ulocate(notice_class)) { + status = realm_ulocate_dispatch(notice, auth, who, server, realm); + } else { + /* redo the recipient */ + if (*notice->z_recipient == '\0') { + sprintf(rlm_recipient, "@%s", realm->name); + notice->z_recipient = rlm_recipient; + /* only send to our realm */ + external = 0; + } else if (bound_for_local_realm(notice) && *notice->z_recipient + == '@') + { + /* we're responsible for getting this message out */ + external = 1; + notice->z_recipient = ""; + } + + /* otherwise, send to local subscribers */ + sendit(notice, auth, who, external); + } + + return(status); +} + +void +realm_init() +{ + Client *client; + Realmname *rlmnames; + Realm *rlm; + int ii, jj, found; + struct in_addr *addresses; + struct hostent *hp; + char list_file[128]; + char rlmprinc[ANAME_SZ+INST_SZ+REALM_SZ+3]; + + sprintf(list_file, "%s/%s", CONFDIR, REALM_LIST_FILE); + rlmnames = get_realm_lists(list_file); + if (!rlmnames) { + zdbug((LOG_DEBUG, "No other realms")); + nrealms = 0; + return; + } + + for (nrealms = 0; *rlmnames[nrealms].name; nrealms++); + + otherrealms = (Realm *)malloc(nrealms * sizeof(Realm)); + if (!otherrealms) { + syslog(LOG_CRIT, "malloc failed in get_realm_addrs"); + abort(); + } + + for (ii = 0; ii < nrealms; ii++) { + rlm = &otherrealms[ii]; + strcpy(rlm->name, rlmnames[ii].name); + + addresses = (struct in_addr *)malloc(rlmnames[ii].nused * sizeof(struct in_addr)); + if (!addresses) { + syslog(LOG_CRIT, "malloc failed in get_realm_addrs"); + abort(); + } + /* convert names to addresses */ + found = 0; + for (jj = 0; jj < rlmnames[ii].nused; jj++) { + hp = gethostbyname(rlmnames[ii].servers[jj]); + if (hp) { + memmove((caddr_t) &addresses[found], (caddr_t)hp->h_addr, sizeof(struct in_addr)); + found++; + } else + syslog(LOG_WARNING, "hostname failed, %s", rlmnames[ii].servers[jj]); + /* free the hostname */ + free(rlmnames[ii].servers[jj]); + } + rlm->count = found; + rlm->addrs = (struct sockaddr_in *)malloc(found * sizeof (struct sockaddr_in)); + if (!rlm->addrs) { + syslog(LOG_CRIT, "malloc failed in get_realm_addrs"); + abort(); + } + for (jj = 0; jj < rlm->count; jj++) { + rlm->addrs[jj].sin_family = AF_INET; + /* use the server port */ + rlm->addrs[jj].sin_port = srv_addr.sin_port; + rlm->addrs[jj].sin_addr = addresses[jj]; + } + client = (Client *) malloc(sizeof(Client)); + if (!client) { + syslog(LOG_CRIT, "malloc failed in get_realm_addrs"); + abort(); + } + memset(&client->addr, 0, sizeof(struct sockaddr_in)); +#ifdef ZEPHYR_USES_KERBEROS + memset(&client->session_key, 0, sizeof(client->session_key)); +#endif + sprintf(rlmprinc, "%s.%s@%s", SERVER_SERVICE, SERVER_INSTANCE, rlm->name); + client->principal = make_string(rlmprinc, 0); + client->last_msg = 0; + client->last_check = 0; + client->last_send = 0; + client->subs = NULL; + client->realm = rlm; + client->addr.sin_family = 0; + client->addr.sin_port = 0; + client->addr.sin_addr.s_addr = 0; + + rlm->client = client; + rlm->idx = random() % rlm->count; + rlm->subs = NULL; + rlm->tkt_try = 0; + free(rlmnames[ii].servers); + free(addresses); + } + free(rlmnames); +} + +static Code_t +realm_ulocate_dispatch(notice, auth, who, server, realm) + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + Server *server; + Realm *realm; +{ + register char *opcode = notice->z_opcode; + Code_t status; + + if (!auth) { + syslog(LOG_WARNING, "unauth locate msg from %s", + inet_ntoa(who->sin_addr)); + clt_ack(notice, who, AUTH_FAILED); + return(ZERR_NONE); + } + + if (!strcmp(opcode, REALM_REQ_LOCATE)) { + ack(notice, who); + ulogin_realm_locate(notice, who, realm); + } else if (!strcmp(opcode, REALM_ANS_LOCATE)) { + ack(notice, who); + ulogin_relay_locate(notice, who); + } else { + syslog(LOG_WARNING, "%s unknown/illegal loc opcode %s", + realm->name, opcode); + nack(notice, who); + } + + return(ZERR_NONE); +} + + +Code_t +realm_control_dispatch(notice, auth, who, server, realm) + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + Server *server; + Realm *realm; +{ + register char *opcode = notice->z_opcode; + Code_t status; + + if (!auth) { + syslog(LOG_WARNING, "unauth ctl msg from %s", + inet_ntoa(who->sin_addr)); + if (server == me_server) + clt_ack(notice, who, AUTH_FAILED); + return(ZERR_NONE); + } + + if (strcmp(notice->z_class_inst, ZEPHYR_CTL_REALM)) { + syslog(LOG_WARNING, "Invalid rlm_dispatch instance %s", + notice->z_class_inst); + return(ZERR_NONE); + } + + if (!strcmp(opcode, REALM_REQ_SUBSCRIBE) || !strcmp(opcode, REALM_ADD_SUBSCRIBE)) { + /* try to add subscriptions */ + /* attempts to get defaults are ignored */ + if ((status = subscr_foreign_user(notice, who, realm)) != ZERR_NONE) { + clt_ack(notice, who, AUTH_FAILED); + } else if (server == me_server) { + server_forward(notice, auth, who); + ack(notice, who); + } + } else if (!strcmp(opcode, REALM_UNSUBSCRIBE)) { + /* try to remove subscriptions */ + if ((status = subscr_realm_cancel(who, notice, realm)) != ZERR_NONE) { + clt_ack(notice, who, NOT_FOUND); + } else if (server == me_server) { + server_forward(notice, auth, who); + ack(notice, who); + } + } else { + syslog(LOG_WARNING, "%s unknown/illegal ctl opcode %s", + realm->name, opcode); + if (server == me_server) + nack(notice, who); + return(ZERR_NONE); + } + return(ZERR_NONE); +} + +void +realm_handoff(notice, auth, who, realm, ack_to_sender) + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + Realm *realm; + int ack_to_sender; +{ +#ifdef ZEPHYR_USES_KERBEROS + Code_t retval; + + if (!auth) { + zdbug((LOG_DEBUG, "realm_sendit unauthentic to realm %s", realm->name)) + realm_sendit(notice, who, auth, realm, ack_to_sender); + } + + if (!ticket_lookup(realm->name)) + if ((retval = ticket_retrieve(realm)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_handoff failed: %s", error_message(retval)); + return; + } + + zdbug((LOG_DEBUG, "realm_sendit to realm %s auth %d", realm->name, auth)); + /* valid ticket available now, send the message */ + realm_sendit_auth(notice, who, auth, realm, ack_to_sender); +#else /* ZEPHYR_USES_KERBEROS */ + realm_sendit(notice, who, auth, realm, ack_to_sender); +#endif /* ZEPHYR_USES_KERBEROS */ +} + +static void +realm_sendit(notice, who, auth, realm, ack_to_sender) + ZNotice_t *notice; + struct sockaddr_in *who; + int auth; + Realm *realm; + int ack_to_sender; +{ + caddr_t pack; + int packlen; + Code_t retval; + Unacked *nacked; + + notice->z_auth = auth; + + /* format the notice */ + if ((retval = ZFormatRawNotice(notice, &pack, &packlen)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit format: %s", + error_message(retval)); + return; + } + + /* now send */ + if ((retval = ZSetDestAddr(&realm->addrs[realm->idx])) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit set addr: %s", + error_message(retval)); + free(pack); + return; + } + if ((retval = ZSendPacket(pack, packlen, 0)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit xmit: %s", error_message(retval)); + free(pack); + return; + } + + /* now we've sent it, mark it as not ack'ed */ + + if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) { + /* no space: just punt */ + syslog(LOG_ERR, "rlm_sendit nack malloc"); + free(pack); + return; + } + + nacked->rexmits = 0; + nacked->packet = pack; + nacked->dest.rlm.rlm_idx = realm - otherrealms; + nacked->dest.rlm.rlm_srv_idx = realm->idx; + nacked->packsz = packlen; + nacked->uid = notice->z_uid; + if (ack_to_sender) + nacked->ack_addr = *who; + else + nacked->ack_addr.sin_addr.s_addr = 0; + + /* set a timer to retransmit */ + nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked); + /* chain in */ + LIST_INSERT(&rlm_nacklist, nacked); + return; +} + +static void +packet_ctl_nack(nackpacket) + Unacked *nackpacket; +{ + ZNotice_t notice; + + /* extract the notice */ + ZParseNotice(nackpacket->packet, nackpacket->packsz, ¬ice); + nack(¬ice, &nackpacket->ack_addr); +} + +static void +rlm_rexmit(arg) + void *arg; +{ + Unacked *nackpacket = (Unacked *) arg; + Code_t retval; + register Realm *realm; + int new_srv_idx; + + zdbug((LOG_DEBUG,"rlm_rexmit")); + + realm = &otherrealms[nackpacket->dest.rlm.rlm_idx]; + + zdbug((LOG_DEBUG, "rlm_rexmit: sending to %s", realm->name)); + + if (rexmit_times[(nackpacket->rexmits + 1)/(realm->count)] == -1) { + /* give a server ack that the packet is lost/realm dead */ + packet_ctl_nack(nackpacket); + LIST_DELETE(nackpacket); + free(nackpacket->packet); + free(nackpacket); + + zdbug((LOG_DEBUG, "rlm_rexmit: %s appears dead", realm->name)); + return; + } + + /* retransmit the packet, trying each server in the realm multiple times */ +#if 0 + new_srv_idx = ((nackpacket->rexmits / NUM_REXMIT_TIMES) + + nackpacket->rlm.rlm_srv_idx) % realm->count; +#else + new_srv_idx = nackpacket->rexmits % realm->count; +#endif + if (new_srv_idx != realm->idx) + realm->idx = new_srv_idx; + + retval = ZSetDestAddr(&realm->addrs[realm->idx]); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_rexmit set addr: %s", error_message(retval)); + } else { + retval = ZSendPacket(nackpacket->packet, nackpacket->packsz, 0); + if (retval != ZERR_NONE) + syslog(LOG_WARNING, "rlm_rexmit xmit: %s", error_message(retval)); + } + /* reset the timer */ + if (rexmit_times[(nackpacket->rexmits + 1)/(realm->count)] != -1) + nackpacket->rexmits++; + + nackpacket->timer = timer_set_rel(rexmit_times[(nackpacket->rexmits)/(realm->count)], rlm_rexmit, nackpacket); + return; +} + +void +realm_dump_realms(fp) + FILE *fp; +{ + register int ii, jj; + + for (ii = 0; ii < nrealms; ii++) { + (void) fprintf(fp, "%d:%s\n", ii, otherrealms[ii].name); + for (jj = 0; jj < otherrealms[ii].count; jj++) { + (void) fprintf(fp, "\t%s\n", + inet_ntoa(otherrealms[ii].addrs[jj].sin_addr)); + } + /* dump the subs */ + subscr_dump_subs(fp, otherrealms[ii].subs); + } +} + + +#ifdef ZEPHYR_USES_KERBEROS +static void +realm_sendit_auth(notice, who, auth, realm, ack_to_sender) + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + Realm *realm; + int ack_to_sender; +{ + char *buffer, *ptr; + caddr_t pack; + int buffer_len, hdrlen, offset, fragsize, ret_len, message_len; + int origoffset, origlen; + Code_t retval; + Unacked *nacked; + char buf[1024], multi[64]; + CREDENTIALS cred; + KTEXT_ST authent; + ZNotice_t partnotice, newnotice; + + offset = 0; + + /* first, build an authent */ + retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm, &cred); + if (retval != GC_OK) { + syslog(LOG_WARNING, "rlm_sendit_auth get_cred: %s", + error_message(retval+krb_err_base)); + return; + } + + retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, realm, 1); + if (retval != MK_AP_OK) { + syslog(LOG_WARNING, "rlm_sendit_auth mk_req: %s", + error_message(retval+krb_err_base)); + return; + } + + retval = ZMakeAscii(buf, sizeof(buf), authent.dat, authent.length); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth mk_ascii: %s", + error_message(retval)); + return; + } + + /* set the dest addr */ + retval = ZSetDestAddr(&realm->addrs[realm->idx]); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth set addr: %s", error_message(retval)); + return; + } + + /* now format the notice, refragmenting if needed */ + newnotice = *notice; + newnotice.z_auth = 1; + newnotice.z_ascii_authent = buf; + newnotice.z_authent_len = authent.length; + + buffer = (char *) malloc(sizeof(ZPacket_t)); + if (!buffer) { + syslog(LOG_ERR, "realm_sendit_auth malloc"); + return; /* DON'T put on nack list */ + } + + buffer_len = sizeof(ZPacket_t); + + retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, &ptr, + NULL); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval)); + free(buffer); + return; + } + +#ifdef NOENCRYPTION + newnotice.z_checksum = 0; +#else + newnotice.z_checksum = + (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, cred.session); +#endif + + retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, + NULL, NULL); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval)); + free(buffer); + return; + } + + /* This is not terribly pretty, but it does do its job. + * If a packet we get that needs to get sent off to another realm is + * too big after we slap on our authent, we refragment it further, + * a la Z_SendFragmentedNotice. This obliviates the need for what + * used to be done in ZFormatAuthenticRealmNotice, as we do it here. + * At some point it should be pulled back out into its own function, + * but only the server uses it. + */ + + if ((newnotice.z_message_len+hdrlen > buffer_len) || + (newnotice.z_message_len+hdrlen > Z_MAXPKTLEN)){ + /* Deallocate buffer, use a local one */ + free(buffer); + + partnotice = *notice; + + partnotice.z_auth = 1; + partnotice.z_ascii_authent = buf; + partnotice.z_authent_len = authent.length; + + origoffset = 0; + origlen = notice->z_message_len; + + if (notice->z_multinotice && strcmp(notice->z_multinotice, "")) + if (sscanf(notice->z_multinotice, "%d/%d", &origoffset, &origlen) != 2) { + syslog(LOG_WARNING, "rlm_sendit_auth frag: parse failed"); + return; + } + +#if 0 + zdbug((LOG_DEBUG,"rlm_send_auth: orig: %d-%d/%d", origoffset, notice->z_message_len, origlen)); +#endif + + fragsize = Z_MAXPKTLEN-hdrlen-Z_FRAGFUDGE; + + while (offset < notice->z_message_len || !notice->z_message_len) { + (void) sprintf(multi, "%d/%d", offset+origoffset, origlen); + partnotice.z_multinotice = multi; + if (offset > 0) { + (void) gettimeofday(&partnotice.z_uid.tv, (struct timezone *)0); + partnotice.z_uid.tv.tv_sec = htonl((u_long) + partnotice.z_uid.tv.tv_sec); + partnotice.z_uid.tv.tv_usec = htonl((u_long) + partnotice.z_uid.tv.tv_usec); + if ((retval = Z_GetMyAddr()) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth addr: %s", error_message(retval)); + return; + } + (void) memcpy((char *)&partnotice.z_uid.zuid_addr, __My_addr, + __My_length); + } + message_len = min(notice->z_message_len-offset, fragsize); + partnotice.z_message = notice->z_message+offset; + partnotice.z_message_len = message_len; + +#if 0 + zdbug((LOG_DEBUG,"rlm_send_auth: new: %d-%d/%d", origoffset+offset, message_len, origlen)); +#endif + + buffer = (char *) malloc(sizeof(ZPacket_t)); + if (!buffer) { + syslog(LOG_ERR, "realm_sendit_auth malloc"); + return; /* DON'T put on nack list */ + } + + retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, &hdrlen, + &ptr, NULL); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval)); + free(buffer); + return; + } + +#ifdef NOENCRYPTION + partnotice.z_checksum = 0; +#else + partnotice.z_checksum = + (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, + cred.session); +#endif + + retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, &hdrlen, + NULL, NULL); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval)); + free(buffer); + return; + } + + ptr = buffer+hdrlen; + + (void) memcpy(ptr, partnotice.z_message, partnotice.z_message_len); + + buffer_len = hdrlen+partnotice.z_message_len; + + /* now send */ + if ((retval = ZSendPacket(buffer, buffer_len, 0)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s", error_message(retval)); + free(buffer); + return; + } + + offset += fragsize; + + if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) { + /* no space: just punt */ + syslog(LOG_ERR, "rlm_sendit_auth nack malloc"); + free(buffer); + return; + } + + nacked->rexmits = 0; + nacked->packet = buffer; + nacked->dest.rlm.rlm_idx = realm - otherrealms; + nacked->dest.rlm.rlm_srv_idx = realm->idx; + nacked->packsz = buffer_len; + nacked->uid = partnotice.z_uid; + + /* Do the ack for the last frag, below */ + if (ack_to_sender) + nacked->ack_addr = *who; + else + nacked->ack_addr.sin_addr.s_addr = 0; + + /* set a timer to retransmit */ + nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked); + + /* chain in */ + LIST_INSERT(&rlm_nacklist, nacked); + + if (!notice->z_message_len) + break; + } +#if 0 + zdbug((LOG_DEBUG, "rlm_sendit_auth frag message sent")); +#endif + } else { + /* This is easy, no further fragmentation needed */ + ptr = buffer+hdrlen; + + (void) memcpy(ptr, newnotice.z_message, newnotice.z_message_len); + + buffer_len = hdrlen+newnotice.z_message_len; + + /* now send */ + if ((retval = ZSendPacket(buffer, buffer_len, 0)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s", error_message(retval)); + free(buffer); + return; + } + +#if 0 + zdbug((LOG_DEBUG, "rlm_sendit_auth message sent")); +#endif + /* now we've sent it, mark it as not ack'ed */ + + if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) { + /* no space: just punt */ + syslog(LOG_ERR, "rlm_sendit_auth nack malloc"); + free(buffer); + return; + } + + nacked->rexmits = 0; + nacked->packet = buffer; + nacked->dest.rlm.rlm_idx = realm - otherrealms; + nacked->dest.rlm.rlm_srv_idx = realm->idx; + nacked->packsz = buffer_len; + nacked->uid = notice->z_uid; + + /* Do the ack for the last frag, below */ + if (ack_to_sender) + nacked->ack_addr = *who; + else + nacked->ack_addr.sin_addr.s_addr = 0; + + /* set a timer to retransmit */ + nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked); + /* chain in */ + LIST_INSERT(&rlm_nacklist, nacked); + } +#if 0 + if (ack_to_sender) + nacked->ack_addr = *who; +#endif + return; +} + +int +ticket_expired(cred) +CREDENTIALS *cred; +{ + /* extra 15 minutes for safety margin */ +#ifdef AFS_LIFETIMES + return (krb_life_to_time(cred->issue_date, cred->lifetime) < NOW + 15*60); +#else /* AFS_LIFETIMES */ + return (cred->issue_date + cred->lifetime*5*60 < NOW + 15*60); +#endif /* AFS_LIFETIMES */ +} + +int +ticket_lookup(realm) +char *realm; +{ + CREDENTIALS cred; + KTEXT_ST authent; + int retval; + + retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm, &cred); + if (retval == GC_OK && !ticket_expired(&cred)) + /* good ticket */ + return(1); + + if (!strcmp(realm, ZGetRealm())) { + get_tgt(); + + /* For Putrify */ + memset(&authent.dat,0,MAX_KTXT_LEN); + authent.mbz=0; + + /* this is local, so try to contact the Kerberos server */ + retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, + realm, 0); + if (retval != KSUCCESS) { + syslog(LOG_ERR, "tkt_lookup: local: %s", + krb_err_txt[retval]); + return(0); + } else { + return(1); + } + } + + return (0); +} + +static Code_t +ticket_retrieve(realm) + Realm *realm; +{ + int pid, retval; + KTEXT_ST authent; + + get_tgt(); + + /* For Putrify */ + memset(&authent.dat,0,MAX_KTXT_LEN); + authent.mbz=0; + + /* Don't lose by trying too often. */ + if (NOW - realm->tkt_try > 5 * 60) { + retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, + realm->name, 0); + realm->tkt_try = NOW; + if (retval != KSUCCESS) { + syslog(LOG_WARNING, "tkt_rtrv: %s: %s", realm, + krb_err_txt[retval]); + return (retval+krb_err_base); + } + return (0); + } else { + return (1); + } +} +#endif /* ZEPHYR_USES_KERBEROS */ + diff --git a/server/server.c b/server/server.c index cb9b121..70a06b9 100644 --- a/server/server.c +++ b/server/server.c @@ -12,18 +12,19 @@ */ #include <zephyr/mit-copyright.h> +#include "zserver.h" +#include <sys/socket.h> #ifndef lint #ifndef SABER -static char rcsid_server_c[] = "$Id$"; +static const char rcsid_server_c[] = "$Id$"; #endif #endif -#include "zserver.h" -#include <sys/socket.h> /* for AF_INET */ -#include <netdb.h> /* for gethostbyname */ -#include <sys/param.h> /* for BSD */ - +#define SRV_NACKTAB_HASHSIZE 1023 +#define SRV_NACKTAB_HASHVAL(which, uid) (((which) ^ (uid).zuid_addr.s_addr ^ \ + (uid).tv.tv_sec ^ (uid).tv.tv_usec) \ + % SRV_NACKTAB_HASHSIZE) /* * Server manager. Deal with traffic to and from other servers. * @@ -32,7 +33,7 @@ static char rcsid_server_c[] = "$Id$"; * void server_shutdown() * * void server_timo(which) - * ZServerDesc_t *which; + * Server *which; * * void server_dispatch(notice, auth, who) * ZNotice_t *notice; @@ -40,24 +41,24 @@ static char rcsid_server_c[] = "$Id$"; * struct sockaddr_in *who; * * void server_recover(client) - * ZClient_t *client; + * Client *client; * * void server_adispatch(notice, auth, who, server) * ZNotice_t *notice; * int auth; * struct sockaddr_in *who; - * ZServerDesc_t *server; + * Server *server; * * void server_forward(notice, auth, who) * ZNotice_t *notice; * int auth; * struct sockaddr_in *who; * - * ZServerDesc_t *server_which_server(who) + * Server *server_which_server(who) * struct sockaddr_in *who; * * void server_kill_clt(client); - * ZClient_t *client; + * Client *client; * * void server_dump_servers(fp); * FILE *fp; @@ -65,68 +66,51 @@ static char rcsid_server_c[] = "$Id$"; * void server_reset(); */ -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -static void - server_flush P((ZServerDesc_t *)), - hello_respond P((struct sockaddr_in *, int, int)), - srv_responded P((struct sockaddr_in *)), - send_msg P((struct sockaddr_in *, char *, int)), - send_msg_list P((struct sockaddr_in *, char *, char **, int, int, int)), - srv_nack_cancel P((ZNotice_t *, struct sockaddr_in *)), - srv_nack_release P((ZServerDesc_t *)), - srv_nack_renumber P((int *)), - server_lost P((ZServerDesc_t *)), - send_stats P((struct sockaddr_in *)), - server_queue P((ZServerDesc_t *, int, caddr_t, int, struct sockaddr_in *)); -#define STATIC /* should be static, but is friend elsewhere */ -STATIC void - server_hello P((ZServerDesc_t *, int)), - setup_server P((ZServerDesc_t *, struct in_addr *)), - srv_rexmit P((void *)), - server_forw_reliable P((ZServerDesc_t *, caddr_t, int, ZNotice_t *)); -static Code_t - admin_dispatch P((ZNotice_t *, int, struct sockaddr_in *, - ZServerDesc_t *)), - recover_clt P((ZNotice_t *, ZServerDesc_t *)), - kill_clt P((ZNotice_t *, ZServerDesc_t *)), - extract_addr P((ZNotice_t *, struct sockaddr_in *)); - +static void server_flush __P((Server *)); +static void hello_respond __P((struct sockaddr_in *, int, int)); +static void srv_responded __P((struct sockaddr_in *)); +static void send_msg __P((struct sockaddr_in *, char *, int)); +static void send_msg_list __P((struct sockaddr_in *, char *, char **, int, + int)); +static void srv_nack_cancel __P((ZNotice_t *, struct sockaddr_in *)); +static void srv_nack_release __P((Server *)); +static void srv_nack_renumber __P((int *)); +static void send_stats __P((struct sockaddr_in *)); +static void server_queue __P((Server *, int, void *, int, + struct sockaddr_in *)); +static void server_hello __P((Server *, int)); +static void setup_server __P((Server *, struct in_addr *)); +static void srv_rexmit __P((void *)); +static void server_forw_reliable __P((Server *, caddr_t, int, ZNotice_t *)); +static Code_t admin_dispatch __P((ZNotice_t *, int, struct sockaddr_in *, + Server *)); +static Code_t kill_clt __P((ZNotice_t *, Server *)); +static Code_t extract_addr __P((ZNotice_t *, struct sockaddr_in *)); #ifdef notdef static Code_t server_register(); #endif -static struct in_addr *get_server_addrs P((int *number)); -#ifndef HESIOD -static char **get_server_list P((char *file)); -static void free_server_list P((char **list)); +static struct in_addr *get_server_addrs __P((int *number)); +#ifndef ZEPHYR_USES_HESIOD +static char **get_server_list __P((char *file)); +static void free_server_list __P((char **list)); #endif -#undef P +static Unacked *srv_nacktab[SRV_NACKTAB_HASHSIZE]; +Server *otherservers; /* points to an array of the known + servers */ +int nservers; /* number of other servers */ +int me_server_idx; /* # of my entry in the array */ - -ZNotAcked_t *srv_nacklist; /* not acked list for server-server - packets */ -ZServerDesc_t *otherservers; /* points to an array of the known - servers */ -int nservers; /* number of other servers */ -int me_server_idx; /* # of my entry in the array */ - -#define ADJUST (1) /* adjust timeout on hello input */ -#define DONT_ADJUST (0) /* don't adjust timeout */ +#define ADJUST (1) /* adjust timeout on hello input */ +#define DONT_ADJUST (0) /* don't adjust timeout */ /* parameters controlling the transitions of the FSM's--patchable with adb */ long timo_up = TIMO_UP; long timo_tardy = TIMO_TARDY; long timo_dead = TIMO_DEAD; -long srv_rexmit_secs = REXMIT_SECS; - /* counters to measure old protocol use */ #ifdef OLD_COMPAT int old_compat_count_uloc = 0; @@ -152,93 +136,85 @@ int zalone; void server_init() { - register int i; - struct in_addr *serv_addr, *server_addrs, limbo_addr; + int i; + struct in_addr *serv_addr, *server_addrs, limbo_addr; - /* we don't need to mask SIGFPE here since when we are called, - the signal handler isn't set up yet. */ + /* we don't need to mask SIGFPE here since when we are called, + the signal handler isn't set up yet. */ - /* talk to hesiod here, set nservers */ - if (!(server_addrs = get_server_addrs(&nservers))) { - syslog(LOG_ERR, "No servers?!?"); - exit(1); - } + /* talk to hesiod here, set nservers */ + server_addrs = get_server_addrs(&nservers); + if (!server_addrs) { + syslog(LOG_ERR, "No servers?!?"); + exit(1); + } #ifdef DEBUG - if (zalone) - nservers = 1; - else + if (zalone) + nservers = 1; + else #endif /* DEBUG */ - /* increment servers to make room for 'limbo' */ - nservers++; - - otherservers = (ZServerDesc_t *) xmalloc(nservers * - sizeof(ZServerDesc_t)); - me_server_idx = -1; - - /* set up limbo */ - limbo_addr.s_addr = (unsigned long) 0; - setup_server(otherservers, &limbo_addr); - timer_reset(otherservers[0].zs_timer); - otherservers[0].zs_timer = (timer) NULL; - otherservers[0].zs_update_queue = NULLZSPT; - otherservers[0].zs_dumping = 0; - - for (serv_addr = server_addrs, i = 1; i < nservers; serv_addr++, i++) { - setup_server(&otherservers[i], serv_addr); - /* is this me? */ - if (serv_addr->s_addr == my_addr.s_addr) { - me_server_idx = i; - otherservers[i].zs_state = SERV_UP; - timer_reset(otherservers[i].zs_timer); - otherservers[i].zs_timer = (timer) NULL; - otherservers[i].zs_update_queue = NULLZSPT; - otherservers[i].zs_dumping = 0; + /* increment servers to make room for 'limbo' */ + nservers++; + + otherservers = (Server *) malloc(nservers * sizeof(Server)); + me_server_idx = -1; + + /* set up limbo */ + limbo_addr.s_addr = 0; + setup_server(otherservers, &limbo_addr); + timer_reset(otherservers[0].timer); + otherservers[0].timer = NULL; + otherservers[0].queue = NULL; + otherservers[0].dumping = 0; + + for (serv_addr = server_addrs, i = 1; i < nservers; serv_addr++, i++) { + setup_server(&otherservers[i], serv_addr); + /* is this me? */ + if (serv_addr->s_addr == my_addr.s_addr) { + me_server_idx = i; + otherservers[i].state = SERV_UP; + timer_reset(otherservers[i].timer); + otherservers[i].timer = NULL; + otherservers[i].queue = NULL; + otherservers[i].dumping = 0; #if 0 - zdbug((LOG_DEBUG,"found myself")); + zdbug((LOG_DEBUG,"found myself")); #endif - } } + } - /* free up the addresses */ - xfree(server_addrs); + /* free up the addresses */ + free(server_addrs); - if (me_server_idx == -1) { - syslog(LOG_WARNING, "I'm a renegade server!"); - otherservers = (ZServerDesc_t *)realloc((caddr_t) otherservers, (unsigned) (++nservers * sizeof(ZServerDesc_t))); - if (!otherservers) { - syslog(LOG_CRIT, "renegade realloc"); - abort(); - } - setup_server(&otherservers[nservers - 1], &my_addr); - /* we are up. */ - otherservers[nservers - 1].zs_state = SERV_UP; - - /* I don't send hello's to myself--cancel the timer */ - timer_reset(otherservers[nservers - 1].zs_timer); - otherservers[nservers - 1].zs_timer = (timer) NULL; - - /* cancel and reschedule all the timers--pointers need - adjusting */ - /* don't reschedule limbo's timer, so start i=1 */ - for (i = 1; i < nservers - 1; i++) { - timer_reset(otherservers[i].zs_timer); - /* all the HELLO's are due now */ - otherservers[i].zs_timer = - timer_set_rel(0L, server_timo, (void *) - &otherservers[i]); - } - me_server_idx = nservers - 1; + if (me_server_idx == -1) { + syslog(LOG_WARNING, "I'm a renegade server!"); + otherservers = (Server *) realloc(otherservers, + ++nservers * sizeof(Server)); + if (!otherservers) { + syslog(LOG_CRIT, "renegade realloc"); + abort(); } - if (!(srv_nacklist = (ZNotAcked_t *) xmalloc(sizeof(ZNotAcked_t)))) { - /* unrecoverable */ - syslog(LOG_CRIT, "srv_nacklist malloc"); - abort(); + setup_server(&otherservers[nservers - 1], &my_addr); + /* we are up. */ + otherservers[nservers - 1].state = SERV_UP; + + /* I don't send hello's to myself--cancel the timer */ + timer_reset(otherservers[nservers - 1].timer); + otherservers[nservers - 1].timer = NULL; + + /* cancel and reschedule all the timers--pointers need + adjusting */ + /* don't reschedule limbo's timer, so start i=1 */ + for (i = 1; i < nservers - 1; i++) { + timer_reset(otherservers[i].timer); + /* all the HELLO's are due now */ + otherservers[i].timer = timer_set_rel(0L, server_timo, + &otherservers[i]); } - (void) memset((caddr_t) srv_nacklist, 0, sizeof(ZNotAcked_t)); - srv_nacklist->q_forw = srv_nacklist->q_back = srv_nacklist; + me_server_idx = nservers - 1; + } - return; } /* @@ -256,191 +232,193 @@ server_init() void server_reset() { - int num_servers; - struct in_addr *server_addrs; - register struct in_addr *serv_addr; - register ZServerDesc_t *servers; - register int i, j; - int *ok_list_new, *ok_list_old; - int num_ok, new_num; + int num_servers; + struct in_addr *server_addrs; + struct in_addr *serv_addr; + Server *servers; + int i, j; + int *ok_list_new, *ok_list_old; + int num_ok, new_num; #if 0 - zdbug((LOG_DEBUG, "server_reset")); + zdbug((LOG_DEBUG, "server_reset")); #endif #ifdef DEBUG - if (zalone) { - syslog(LOG_INFO, "server_reset while alone, punt"); - return; - } + if (zalone) { + syslog(LOG_INFO, "server_reset while alone, punt"); + return; + } #endif /* DEBUG */ - /* Find out what servers are supposed to be known. */ - if (!(server_addrs = get_server_addrs(&num_servers))) { - syslog(LOG_ERR, "server_reset no servers. nothing done."); - return; - } - ok_list_new = (int *) xmalloc (num_servers * sizeof (int)); - if (ok_list_new == (int *) 0) { - syslog(LOG_ERR, "server_reset no mem new"); - return; - } - ok_list_old = (int *) xmalloc (nservers * sizeof (int)); - if (ok_list_old == (int *) 0) { - syslog(LOG_ERR, "server_reset no mem old"); - xfree(ok_list_new); - return; - } + /* Find out what servers are supposed to be known. */ + server_addrs = get_server_addrs(&num_servers); + if (!server_addrs) { + syslog(LOG_ERR, "server_reset no servers. nothing done."); + return; + } + ok_list_new = (int *) malloc(num_servers * sizeof(int)); + if (!ok_list_new) { + syslog(LOG_ERR, "server_reset no mem new"); + return; + } + ok_list_old = (int *) malloc(nservers * sizeof(int)); + if (!ok_list_old) { + syslog(LOG_ERR, "server_reset no mem old"); + free(ok_list_new); + return; + } - (void) memset((char *)ok_list_old, 0, nservers * sizeof(int)); - (void) memset((char *)ok_list_new, 0, num_servers * sizeof(int)); + memset(ok_list_old, 0, nservers * sizeof(int)); + memset(ok_list_new, 0, num_servers * sizeof(int)); - /* reset timers--pointers will move */ - for (j = 1; j < nservers; j++) { /* skip limbo */ - if (j == me_server_idx) - continue; - timer_reset(otherservers[j].zs_timer); - otherservers[j].zs_timer = (timer) 0; + /* reset timers--pointers will move */ + for (j = 1; j < nservers; j++) { /* skip limbo */ + if (j == me_server_idx) + continue; + timer_reset(otherservers[j].timer); + otherservers[j].timer = NULL; + } + + /* check off entries on new list which are on old list. + check off entries on old list which are on new list. */ + + /* count limbo as "OK" */ + num_ok = 1; + ok_list_old[0] = 1; /* limbo is OK */ + + for (serv_addr = server_addrs, i = 0; i < num_servers; serv_addr++, i++) { + for (j = 1; j < nservers; j++) { /* j = 1 since we skip limbo */ + if (otherservers[j].addr.sin_addr.s_addr == serv_addr->s_addr) { + /* if server is on both lists, mark */ + ok_list_new[i] = 1; + ok_list_old[j] = 1; + num_ok++; + break; /* for j loop */ + } } + } - /* check off entries on new list which are on old list. - check off entries on old list which are on new list. - */ - - /* count limbo as "OK" */ - num_ok = 1; - ok_list_old[0] = 1; /* limbo is OK */ - - for (serv_addr = server_addrs, i = 0; - i < num_servers; - serv_addr++, i++) /* for each new server */ - for (j = 1; j < nservers; j++) /* j = 1 since we skip limbo */ - if (otherservers[j].zs_addr.sin_addr.s_addr == - serv_addr->s_addr) { - /* if server is on both lists, mark */ - ok_list_new[i] = 1; - ok_list_old[j] = 1; - num_ok++; - break; /* for j loop */ - } - - /* remove any dead servers on old list not on new list. */ - if (num_ok < nservers) { - int *srv; - new_num = 1; /* limbo */ - /* count number of servers to keep */ - for (j = 1; j < nservers; j++) - /* since we are never SERV_DEAD, the following - test prevents removing ourself from the list */ - if (ok_list_old[j] || - (otherservers[j].zs_state != SERV_DEAD)) { - syslog(LOG_INFO, "keeping server %s", - otherservers[j].addr); - new_num++; - } - if (new_num < nservers) { - servers = (ZServerDesc_t *) xmalloc(new_num * sizeof(ZServerDesc_t)); - if (!servers) { - syslog(LOG_CRIT, "server_reset server malloc"); - abort(); - } - i = 1; - servers[0] = otherservers[0]; /* copy limbo */ - - srv = (int*) xmalloc (nservers * sizeof (int)); - (void) memset (srv, 0, nservers * sizeof (int)); - - /* copy the kept servers */ - for (j = 1; j < nservers; j++) { /* skip limbo */ - if (ok_list_old[j] || - otherservers[j].zs_state != SERV_DEAD) { - servers[i] = otherservers[j]; - srv[j] = i; - i++; - } else { - syslog(LOG_INFO, "flushing server %s", - otherservers[j].addr); - server_flush(&otherservers[j]); - srv[j] = -1; - } - - } - srv_nack_renumber (srv); - hostm_renumber_servers (srv); - - xfree(srv); - xfree(otherservers); - otherservers = servers; - nservers = new_num; + /* remove any dead servers on old list not on new list. */ + if (num_ok < nservers) { + int *srv; + + new_num = 1; /* limbo */ + /* count number of servers to keep */ + for (j = 1; j < nservers; j++) { + /* since we are never SERV_DEAD, the following + test prevents removing ourself from the list */ + if (ok_list_old[j] || (otherservers[j].state != SERV_DEAD)) { + syslog(LOG_INFO, "keeping server %s", + otherservers[j].addr_str); + new_num++; + } + } + if (new_num < nservers) { + servers = (Server *) malloc(new_num * sizeof(Server)); + if (!servers) { + syslog(LOG_CRIT, "server_reset server malloc"); + abort(); + } + i = 1; + servers[0] = otherservers[0]; /* copy limbo */ + + srv = (int *) malloc(nservers * sizeof(int)); + memset(srv, 0, nservers * sizeof(int)); + + /* copy the kept servers */ + for (j = 1; j < nservers; j++) { /* skip limbo */ + if (ok_list_old[j] || + otherservers[j].state != SERV_DEAD) { + servers[i] = otherservers[j]; + srv[j] = i; + i++; + } else { + syslog(LOG_INFO, "flushing server %s", + otherservers[j].addr_str); + server_flush(&otherservers[j]); + srv[j] = -1; } + + } + srv_nack_renumber(srv); + + free(srv); + free(otherservers); + otherservers = servers; + nservers = new_num; } - /* add any new servers on new list not on old list. */ - new_num = 0; - for (i = 0; i < num_servers; i++) - if (!ok_list_new[i]) - new_num++; - /* new_num is number of extras. */ - nservers += new_num; - otherservers = (ZServerDesc_t *)realloc((caddr_t) otherservers, (unsigned) (nservers * sizeof(ZServerDesc_t))); - if (!otherservers) { - syslog(LOG_CRIT, "server_reset realloc"); - abort(); + } + + /* add any new servers on new list not on old list. */ + new_num = 0; + for (i = 0; i < num_servers; i++) { + if (!ok_list_new[i]) + new_num++; + } + + /* new_num is number of extras. */ + nservers += new_num; + otherservers = (Server *) realloc(otherservers, nservers * sizeof(Server)); + if (!otherservers) { + syslog(LOG_CRIT, "server_reset realloc"); + abort(); + } + + me_server_idx = 0; + for (j = 1; j < nservers - new_num; j++) { + if (otherservers[j].addr.sin_addr.s_addr == my_addr.s_addr) { + me_server_idx = j; + break; } + } + if (!me_server_idx) { + syslog(LOG_CRIT, "can't find myself"); + abort(); + } - me_server_idx = 0; - for (j = 1; j < nservers - new_num; j++) - if (otherservers[j].zs_addr.sin_addr.s_addr == - my_addr.s_addr) { - me_server_idx = j; - break; - } - if (!me_server_idx) { - syslog(LOG_CRIT, "can't find myself"); - abort(); + /* fill in otherservers with the new servers */ + for (i = 0; i < num_servers; i++) { + if (!ok_list_new[i]) { + setup_server(&otherservers[nservers - (new_num--)], + &server_addrs[i]); + syslog(LOG_INFO, "adding server %s", inet_ntoa(server_addrs[i])); } - - /* fill in otherservers with the new servers */ - for (i = 0; i < num_servers; i++) - if (!ok_list_new[i]) { - setup_server(&otherservers[nservers - (new_num--)], - &server_addrs[i]); - syslog(LOG_INFO, "adding server %s", - inet_ntoa(server_addrs[i])); - } - xfree(server_addrs); - /* reset timers, to go off now. - We can't get a time-left indication (bleagh!) - so we expire them all now. This will generally - be non-destructive. We assume that when this code is - entered via a SIGHUP trigger that a system wizard - is watching the goings-on to make sure things straighten - themselves out. - */ - for (i = 1; i < nservers; i++) /* skip limbo */ - if (i != me_server_idx && !otherservers[i].zs_timer) { - otherservers[i].zs_timer = - timer_set_rel(0L, server_timo, - (void *) &otherservers[i]); + } + + free(server_addrs); + /* reset timers, to go off now. + We can't get a time-left indication (bleagh!) + so we expire them all now. This will generally + be non-destructive. We assume that when this code is + entered via a SIGHUP trigger that a system wizard + is watching the goings-on to make sure things straighten + themselves out. + */ + for (i = 1; i < nservers; i++) { /* skip limbo */ + if (i != me_server_idx && !otherservers[i].timer) { + otherservers[i].timer = + timer_set_rel(0L, server_timo, &otherservers[i]); #if 0 - zdbug((LOG_DEBUG, "reset timer for %s", - otherservers[i].addr)); -#endif - } - xfree(ok_list_old); - xfree(ok_list_new); + zdbug((LOG_DEBUG, "reset timer for %s", + otherservers[i].addr_str)); +#endif + } + } + free(ok_list_old); + free(ok_list_new); #if 0 - zdbug((LOG_DEBUG, "server_reset: %d servers now", nservers)); + zdbug((LOG_DEBUG, "server_reset: %d servers now", nservers)); #endif - return; } /* note: these must match the order given in zserver.h */ static char * srv_states[] = { - "SERV_UP", - "SERV_TARDY", - "SERV_DEAD", - "SERV_STARTING" + "SERV_UP", + "SERV_TARDY", + "SERV_DEAD", + "SERV_STARTING" }; /* @@ -453,58 +431,53 @@ srv_states[] = { */ void -#ifdef __STDC__ -server_timo(void* arg) -#else server_timo(arg) - void* arg; -#endif + void *arg; { - ZServerDesc_t *which = (ZServerDesc_t *) arg; - int auth = 0; + Server *which = (Server *) arg; + int auth = 0; #if 0 - zdbug((LOG_DEBUG,"srv_timo: %s", which->addr)); + zdbug((LOG_DEBUG,"srv_timo: %s", which->addr_str)); #endif - /* change state and reset if appropriate */ - switch(which->zs_state) { - case SERV_DEAD: /* leave him dead */ - server_flush(which); - auth = 1; - break; - case SERV_UP: /* he's now tardy */ - which->zs_state = SERV_TARDY; - which->zs_numsent = 0; - which->zs_timeout = timo_tardy; - auth = 0; - break; - case SERV_TARDY: - case SERV_STARTING: - if (which->zs_numsent >= ((which->zs_state == SERV_TARDY) ? - H_NUM_TARDY : - H_NUM_STARTING)) { - /* he hasn't answered, assume DEAD */ - which->zs_state = SERV_DEAD; - which->zs_numsent = 0; - which->zs_timeout = timo_dead; - server_lost(which); - } - auth = 0; - break; - default: - syslog(LOG_ERR,"Bad server state, server 0x%x\n",which); - abort(); + /* change state and reset if appropriate */ + switch(which->state) { + case SERV_DEAD: /* leave him dead */ + server_flush(which); + auth = 1; + break; + case SERV_UP: /* he's now tardy */ + which->state = SERV_TARDY; + which->num_hello_sent = 0; + which->timeout = timo_tardy; + auth = 0; + break; + case SERV_TARDY: + case SERV_STARTING: + if (which->num_hello_sent >= ((which->state == SERV_TARDY) ? + H_NUM_TARDY : + H_NUM_STARTING)) { + /* he hasn't answered, assume DEAD */ + which->state = SERV_DEAD; + which->num_hello_sent = 0; + which->timeout = timo_dead; + srv_nack_release(which); } - /* now he's either TARDY, STARTING, or DEAD - We send a "hello," which increments the counter */ + auth = 0; + break; + default: + syslog(LOG_ERR,"Bad server state, server 0x%x\n",which); + abort(); + } + /* now he's either TARDY, STARTING, or DEAD + We send a "hello," which increments the counter */ #if 0 - zdbug((LOG_DEBUG, "srv %s is %s", which->addr, - srv_states[(int) which->zs_state])); + zdbug((LOG_DEBUG, "srv %s is %s", which->addr_str, + srv_states[which->state])); #endif - server_hello(which, auth); - /* reschedule the timer */ - which->zs_timer = timer_set_rel(which->zs_timeout, server_timo, - (void *) which); + server_hello(which, auth); + /* reschedule the timer */ + which->timer = timer_set_rel(which->timeout, server_timo, which); } /* @@ -514,67 +487,64 @@ server_timo(arg) /*ARGSUSED*/ Code_t server_dispatch(notice, auth, who) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; { - ZServerDesc_t *server; - struct sockaddr_in newwho; - Code_t status; - ZSTRING *notice_class; - + Server *server; + struct sockaddr_in newwho; + Code_t status; + String *notice_class; #if 0 - zdbug((LOG_DEBUG, "server_dispatch")); + zdbug((LOG_DEBUG, "server_dispatch")); #endif - if (notice->z_kind == SERVACK) { - srv_nack_cancel(notice, who); - srv_responded(who); - return(ZERR_NONE); - } - /* set up a who for the real origin */ - (void) memset((caddr_t) &newwho, 0, sizeof(newwho)); - newwho.sin_family = AF_INET; - newwho.sin_addr.s_addr = notice->z_sender_addr.s_addr; - newwho.sin_port = notice->z_port; - - server = server_which_server(who); - - /* we can dispatch to routines safely here, since they will - return ZSRV_REQUEUE if appropriate. We bounce this back - to the caller, and the caller will re-queue the message - for us to process later. */ - - notice_class = make_zstring(notice->z_class,1); - - if (class_is_admin(notice_class)) { - /* admins don't get acked, else we get a packet loop */ - /* will return requeue if bdump request and dumping */ - i_s_admins.val++; - return(admin_dispatch(notice, auth, who, server)); - } else if (class_is_control(notice_class)) { - status = control_dispatch(notice, auth, &newwho, server); - i_s_ctls.val++; - } - else if (class_is_ulogin(notice_class)) { - status = ulogin_dispatch(notice, auth, &newwho, server); - i_s_logins.val++; - } - else if (class_is_ulocate(notice_class)) { - status = ulocate_dispatch(notice, auth, &newwho, server); - i_s_locates.val++; - } - else { - /* shouldn't come from another server */ - syslog(LOG_WARNING, "srv_disp: pkt cls %s", - notice->z_class); - status = ZERR_NONE; /* XXX */ - } - if (status != ZSRV_REQUEUE) - ack(notice, who); /* acknowledge it if processed */ - free_zstring(notice_class); - return(status); + if (notice->z_kind == SERVACK) { + srv_nack_cancel(notice, who); + srv_responded(who); + return ZERR_NONE; + } + /* set up a who for the real origin */ + memset(&newwho, 0, sizeof(newwho)); + newwho.sin_family = AF_INET; + newwho.sin_addr.s_addr = notice->z_sender_addr.s_addr; + newwho.sin_port = notice->z_port; + + server = server_which_server(who); + + /* we can dispatch to routines safely here, since they will + return ZSRV_REQUEUE if appropriate. We bounce this back + to the caller, and the caller will re-queue the message + for us to process later. */ + + notice_class = make_string(notice->z_class, 1); + + if (realm_which_realm(&newwho)) + status = realm_dispatch(notice, auth, &newwho, server); + else if (class_is_admin(notice_class)) { + /* admins don't get acked, else we get a packet loop */ + /* will return requeue if bdump request and dumping */ + i_s_admins.val++; + return admin_dispatch(notice, auth, who, server); + } else if (class_is_control(notice_class)) { + status = control_dispatch(notice, auth, &newwho, server); + i_s_ctls.val++; + } else if (class_is_ulogin(notice_class)) { + status = ulogin_dispatch(notice, auth, &newwho, server); + i_s_logins.val++; + } else if (class_is_ulocate(notice_class)) { + status = ulocate_dispatch(notice, auth, &newwho, server); + i_s_locates.val++; + } else { + /* shouldn't come from another server */ + syslog(LOG_WARNING, "srv_disp: pkt cls %s", notice->z_class); + status = ZERR_NONE; /* XXX */ + } + if (status != ZSRV_REQUEUE) + ack(notice, who); /* acknowledge it if processed */ + free_string(notice_class); + return status; } #ifdef notdef @@ -585,165 +555,120 @@ server_dispatch(notice, auth, who) /*ARGSUSED*/ static Code_t server_register(notice, auth, who) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; { - ZServerDesc_t *temp; - register int i; - long timerval; + Server *temp; + int i; + long timerval; - if (who->sin_port != sock_sin.sin_port) { + if (who->sin_port != srv_addr.sin_port) { #if 0 - zdbug((LOG_DEBUG, "srv_register wrong port %d", - ntohs(who->sin_port))); + zdbug((LOG_DEBUG, "srv_wrong port %d", ntohs(who->sin_port))); #endif - return 1; - } - /* Not yet... talk to ken about authenticators */ + return 1; + } + /* Not yet... talk to ken about authenticators */ #ifdef notdef - if (!auth) { + if (!auth) { #if 0 - zdbug((LOG_DEBUG, "srv_register unauth")); + zdbug((LOG_DEBUG, "srv_unauth")); #endif - return 1; - } + return 1; + } #endif /* notdef */ - /* OK, go ahead and set him up. */ - temp = (ZServerDesc_t *)xmalloc((unsigned) ((nservers + 1) * sizeof(ZServerDesc_t))); - if (!temp) { - syslog(LOG_CRIT, "srv_reg malloc"); - return 1; - } + /* OK, go ahead and set him up. */ + temp = (Server *) malloc((nservers + 1) * sizeof(Server)); + if (!temp) { + syslog(LOG_CRIT, "srv_reg malloc"); + return 1; + } - START_CRITICAL_CODE; - - (void) memcpy((caddr_t) temp, (caddr_t) otherservers, - nservers * sizeof(ZServerDesc_t)); - xfree(otherservers); - otherservers = temp; - /* don't reschedule limbo's timer, so start i=1 */ - for (i = 1; i < nservers; i++) { - if (i == me_server_idx) /* don't reset myself */ - continue; - /* reschedule the timers--we moved otherservers */ - timerval = timer_when(otherservers[i].zs_timer); - timer_reset(otherservers[i].zs_timer); - otherservers[i].zs_timer = timer_set_abs(timerval, server_timo, (caddr_t) &otherservers[i]); - } - setup_server(&otherservers[nservers], &who->sin_addr); - otherservers[nservers].zs_state = SERV_STARTING; - otherservers[nservers].zs_timeout = timo_tardy; - otherservers[nservers].zs_update_queue = NULLZSPT; - otherservers[nservers].zs_dumping = 0; + memcpy(temp, otherservers, nservers * sizeof(Server)); + free(otherservers); + otherservers = temp; + /* don't reschedule limbo's timer, so start i=1 */ + for (i = 1; i < nservers; i++) { + if (i == me_server_idx) /* don't reset myself */ + continue; + /* reschedule the timers--we moved otherservers */ + timerval = timer_when(otherservers[i].timer); + timer_reset(otherservers[i].timer); + otherservers[i].timer = timer_set_abs(timerval, server_timo, + &otherservers[i]); + } + setup_server(&otherservers[nservers], &who->sin_addr); + otherservers[nservers].state = SERV_STARTING; + otherservers[nservers].timeout = timo_tardy; + otherservers[nservers].update_queue = NULL; + otherservers[nservers].dumping = 0; - nservers++; + nservers++; #if 0 - zdbug((LOG_DEBUG, "srv %s is %s", otherservers[nservers].addr, - srv_states[(int) otherservers[nservers].zs_state])); + zdbug((LOG_DEBUG, "srv %s is %s", otherservers[nservers].addr_str, + srv_states[otherservers[nservers].state])); #endif - END_CRITICAL_CODE; - - return 0; + return 0; } #endif /* - * Recover a host whose client has stopped responding. - * The hostm_ module takes care of pings, timeouts, etc. - */ - -void -server_recover(client) - ZClient_t *client; -{ - ZServerDesc_t *server; - char *lyst[2]; - char buf[512]; - -#if 0 - zdbug((LOG_DEBUG,"server recover")); -#endif - if ((server = hostm_find_server(&client->zct_sin.sin_addr)) != - NULLZSDT) { - if (server == limbo_server) { -#if 0 - zdbug((LOG_DEBUG, "no server to recover")); -#endif - return; - } else if (server == me_server) { - /* send a ping, set up a timeout, and return */ - hostm_losing(client, hostm_find_host(&client->zct_sin.sin_addr)); - return; - } else { - /* some other server */ - lyst[0] = inet_ntoa(client->zct_sin.sin_addr); - (void) sprintf(buf, "%d", ntohs(client->zct_sin.sin_port)); - lyst[1] = buf; - send_msg_list(&server->zs_addr, ADMIN_LOST_CLT, - lyst, 2, 0, server - otherservers); - return; - } - } else - syslog(LOG_ERR, "srv_recover: no host for client"); - return; -} - -/* * Tell the other servers that this client died. */ void server_kill_clt(client) - ZClient_t *client; + Client *client; { - register int i; - char buf[512], *lyst[2]; - ZNotice_t notice; - register ZNotice_t *pnotice; /* speed hack */ - caddr_t pack; - int packlen, auth; - Code_t retval; - - lyst[0] = inet_ntoa(client->zct_sin.sin_addr), - (void) sprintf(buf, "%d", ntohs(client->zct_sin.sin_port)); - lyst[1] = buf; + int i; + char buf[512], *lyst[2]; + ZNotice_t notice; + ZNotice_t *pnotice; /* speed hack */ + caddr_t pack; + int packlen, auth; + Code_t retval; + + lyst[0] = inet_ntoa(client->addr.sin_addr), + sprintf(buf, "%d", ntohs(client->addr.sin_port)); + lyst[1] = buf; #if 0 - zdbug((LOG_DEBUG, "server kill clt %s/%s", lyst[0], lyst[1])); + zdbug((LOG_DEBUG, "server kill clt %s/%s", lyst[0], lyst[1])); #endif - pnotice = ¬ice; + pnotice = ¬ice; - pnotice->z_kind = ACKED; + pnotice->z_kind = ACKED; - pnotice->z_port = sock_sin.sin_port; - pnotice->z_class = ZEPHYR_ADMIN_CLASS; - pnotice->z_class_inst = ""; - pnotice->z_opcode = ADMIN_KILL_CLT; - pnotice->z_sender = myname; /* myname is the hostname */ - pnotice->z_recipient = ""; - pnotice->z_default_format = ""; - pnotice->z_num_other_fields = 0; + pnotice->z_port = srv_addr.sin_port; + pnotice->z_class = ZEPHYR_ADMIN_CLASS; + pnotice->z_class_inst = ""; + pnotice->z_opcode = ADMIN_KILL_CLT; + pnotice->z_sender = myname; /* myname is the hostname */ + pnotice->z_recipient = ""; + pnotice->z_default_format = ""; + pnotice->z_num_other_fields = 0; - /* XXX */ - auth = 0; + /* XXX */ + auth = 0; - /* don't tell limbo to flush, start at 1*/ - for (i = 1; i < nservers; i++) { - if (i == me_server_idx) /* don't xmit to myself */ - continue; - if (otherservers[i].zs_state == SERV_DEAD) - continue; - - if ((retval = ZFormatNoticeList(pnotice, lyst, 2, &pack, &packlen, auth ? ZAUTH : ZNOAUTH)) != ZERR_NONE) { - syslog(LOG_WARNING, "kill_clt format: %s", - error_message(retval)); - return; - } - server_forw_reliable(&otherservers[i], pack, packlen, pnotice); + /* don't tell limbo to flush, start at 1*/ + for (i = 1; i < nservers; i++) { + if (i == me_server_idx) /* don't xmit to myself */ + continue; + if (otherservers[i].state == SERV_DEAD) + continue; + + retval = ZFormatNoticeList(pnotice, lyst, 2, &pack, &packlen, + auth ? ZAUTH : ZNOAUTH); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "kill_clt format: %s", error_message(retval)); + return; } + server_forw_reliable(&otherservers[i], pack, packlen, pnotice); + } } /* @@ -752,76 +677,34 @@ server_kill_clt(client) static Code_t kill_clt(notice, server) - ZNotice_t *notice; - ZServerDesc_t *server; + ZNotice_t *notice; + Server *server; { - struct sockaddr_in who; - ZHostList_t *host; - ZClient_t *client; + struct sockaddr_in who; + Client *client; #if 0 - zdbug((LOG_DEBUG, "kill_clt")); + zdbug((LOG_DEBUG, "kill_clt")); #endif - if (extract_addr(notice, &who) != ZERR_NONE) - return(ZERR_NONE); /* XXX */ - if (!(host = hostm_find_host(&who.sin_addr))) { - syslog(LOG_NOTICE, "kill_clt: no such host (%s, from %s)", - inet_ntoa (who.sin_addr), server->addr); - return(ZERR_NONE); /* XXX */ - } - if (host->zh_locked) - return(ZSRV_REQUEUE); - if (!(client = client_which_client(&who, notice))) { - syslog(LOG_NOTICE, "kill_clt: no such client (%s/%d) from %s", - inet_ntoa (who.sin_addr), ntohs (who.sin_port), - server->addr); - return(ZERR_NONE); /* XXX */ - } -#if 0 - if (zdebug || 1) - syslog(LOG_DEBUG, "kill_clt clt_dereg %s/%d from %s", - inet_ntoa (who.sin_addr), ntohs (who.sin_port), - server->addr); + if (extract_addr(notice, &who) != ZERR_NONE) + return ZERR_NONE; /* XXX */ + client = client_which_client(&who.sin_addr, notice); + if (!client) { + syslog(LOG_NOTICE, "kill_clt: no such client (%s/%d) from %s", + inet_ntoa(who.sin_addr), ntohs(who.sin_port), + server->addr_str); + return ZERR_NONE; /* XXX */ + } +#if 1 + if (zdebug || 1) { + syslog(LOG_DEBUG, "kill_clt clt_dereg %s/%d from %s", + inet_ntoa(who.sin_addr), ntohs(who.sin_port), server->addr_str); + } #endif - hostm_lose_ignore(client); - /* remove the locations, too */ - client_deregister(client, host, 1); - return(ZERR_NONE); -} - -/* - * Another server asked us to initiate recovery protocol with the hostmanager - */ -static Code_t -recover_clt(notice, server) - register ZNotice_t *notice; - ZServerDesc_t *server; -{ - struct sockaddr_in who; - ZClient_t *client; - ZHostList_t *host; - Code_t status; - - if ((status = extract_addr(notice, &who)) != ZERR_NONE) - return(status); - if (!(host = hostm_find_host(&who.sin_addr))) { - syslog(LOG_NOTICE, - "recover_clt: host not found (%s, from %s)", - inet_ntoa (who.sin_addr), server->addr); - return(ZERR_NONE); /* XXX */ - } - if (host->zh_locked) - return(ZSRV_REQUEUE); - if (!(client = client_which_client(&who, notice))) { - syslog(LOG_NOTICE, - "recover_clt: client not found (%s/%d, from %s)", - inet_ntoa (who.sin_addr), ntohs (who.sin_port), - server->addr); - return(ZERR_NONE); /* XXX */ - } - hostm_losing(client, host); - return(ZERR_NONE); + /* remove the locations, too */ + client_deregister(client, 1); + return ZERR_NONE; } /* @@ -830,29 +713,29 @@ recover_clt(notice, server) static Code_t extract_addr(notice, who) - ZNotice_t *notice; - struct sockaddr_in *who; + ZNotice_t *notice; + struct sockaddr_in *who; { - register char *cp = notice->z_message; + char *cp = notice->z_message; - if (!notice->z_message_len) { - syslog(LOG_WARNING, "bad addr pkt"); - return(ZSRV_PKSHORT); - } - who->sin_addr.s_addr = inet_addr(notice->z_message); + if (!notice->z_message_len) { + syslog(LOG_WARNING, "bad addr pkt"); + return ZSRV_PKSHORT; + } + who->sin_addr.s_addr = inet_addr(notice->z_message); - cp += strlen(cp) + 1; - if (cp >= notice->z_message + notice->z_message_len) { - syslog(LOG_WARNING, "short addr pkt"); - return(ZSRV_PKSHORT); - } - who->sin_port = notice->z_port = htons((u_short) atoi(cp)); - who->sin_family = AF_INET; + cp += strlen(cp) + 1; + if (cp >= notice->z_message + notice->z_message_len) { + syslog(LOG_WARNING, "short addr pkt"); + return ZSRV_PKSHORT; + } + who->sin_port = notice->z_port = htons((u_short) atoi(cp)); + who->sin_family = AF_INET; #if 0 - zdbug((LOG_DEBUG,"ext %s/%d", inet_ntoa(who->sin_addr), - ntohs(who->sin_port))); + zdbug((LOG_DEBUG,"ext %s/%d", inet_ntoa(who->sin_addr), + ntohs(who->sin_port))); #endif - return(ZERR_NONE); + return ZERR_NONE; } /* @@ -861,29 +744,13 @@ extract_addr(notice, who) static void server_flush(which) - register ZServerDesc_t *which; + Server *which; { - register ZHostList_t *hst; - #if 0 - if (zdebug) - syslog (LOG_DEBUG, "server_flush %s", which->addr); + if (zdebug) + syslog(LOG_DEBUG, "server_flush %s", which->addr_str); #endif - if (!which->zs_hosts) /* no data to flush */ - return; - - for (hst = which->zs_hosts->q_forw; - hst != which->zs_hosts; - hst = which->zs_hosts->q_forw) { - /* for each host, flush all data */ -#if 0 - if (zdebug) - syslog (LOG_DEBUG, "... host %s", - inet_ntoa (hst->zh_addr.sin_addr)); -#endif - hostm_flush(hst, which); - } - srv_nack_release(which); + srv_nack_release(which); } /* @@ -891,14 +758,13 @@ server_flush(which) * Authenticate if auth is set. */ -STATIC void +static void server_hello(which, auth) - ZServerDesc_t *which; - int auth; + Server *which; + int auth; { - send_msg(&which->zs_addr, ADMIN_HELLO, auth); - (which->zs_numsent)++; - return; + send_msg(&which->addr, ADMIN_HELLO, auth); + which->num_hello_sent++; } /* @@ -908,83 +774,54 @@ server_hello(which, auth) /*ARGSUSED*/ static Code_t admin_dispatch(notice, auth, who, server) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - ZServerDesc_t *server; + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + Server *server; { - register char *opcode = notice->z_opcode; - Code_t status = ZERR_NONE; + char *opcode = notice->z_opcode; + Code_t status = ZERR_NONE; #if 0 - zdbug((LOG_DEBUG, "ADMIN received")); + zdbug((LOG_DEBUG, "ADMIN received")); #endif - if (!strcmp(opcode, ADMIN_HELLO)) { - hello_respond(who, ADJUST, auth); - } else if (!strcmp(opcode, ADMIN_IMHERE)) { - srv_responded(who); - } else if (!strcmp(opcode, ADMIN_SHUTDOWN)) { + if (strcmp(opcode, ADMIN_HELLO) == 0) { + hello_respond(who, ADJUST, auth); + } else if (strcmp(opcode, ADMIN_IMHERE) == 0) { + srv_responded(who); + } else if (strcmp(opcode, ADMIN_SHUTDOWN) == 0) { #if 0 - zdbug((LOG_DEBUG, "server shutdown")); + zdbug((LOG_DEBUG, "server shutdown")); #endif - /* we need to transfer all of its hosts to limbo */ - if (server) { - server_lost(server); - server->zs_state = SERV_DEAD; - server->zs_timeout = timo_dead; - /* don't worry about the timer, it will - be set appropriately on the next send */ + if (server) { + srv_nack_release(server); + server->state = SERV_DEAD; + server->timeout = timo_dead; + /* don't worry about the timer, it will + be set appropriately on the next send */ #if 0 - zdbug((LOG_DEBUG, "srv %s is %s", server->addr, - srv_states[(int) server->zs_state])); + zdbug((LOG_DEBUG, "srv %s is %s", server->addr_str, + srv_states[server->state])); #endif } - } else if (!strcmp(opcode, ADMIN_BDUMP)) { -#ifdef CONCURRENT -#if 0 /* If another dump is in progress, it'll likely not - finish in time for us to catch the server's - bdump-waiting period. So don't bother. */ - if (bdumping) - return(ZSRV_REQUEUE); -#else - if (bdumping) - return ZERR_NONE; -#endif -#endif - bdump_get(notice, auth, who, server); - } else if (!strcmp(opcode, ADMIN_LOST_CLT)) { - status = recover_clt(notice, server); - if (status == ZERR_NONE) - ack(notice, who); - } else if (!strcmp(opcode, ADMIN_KILL_CLT)) { - status = kill_clt(notice, server); - if (status == ZERR_NONE) - ack(notice, who); - } else - syslog(LOG_WARNING, "ADMIN unknown opcode %s",opcode); - return(status); + } else if (strcmp(opcode, ADMIN_BDUMP) == 0) { + /* Ignore a brain dump request if this is a brain dump packet + * or a packet being processed concurrently during a brain + * dump. */ + if (bdumping || bdump_concurrent) + return ZERR_NONE; + bdump_get(notice, auth, who, server); + } else if (strcmp(opcode, ADMIN_KILL_CLT) == 0) { + status = kill_clt(notice, server); + if (status == ZERR_NONE) + ack(notice, who); + } else { + syslog(LOG_WARNING, "ADMIN unknown opcode %s",opcode); + } + return status; } -/* - * Transfer all the hosts on server to limbo - */ - -static void -server_lost(server) - ZServerDesc_t *server; -{ - register ZHostList_t *host, *hishost; - - hishost = server->zs_hosts; - for (host = hishost->q_forw; - host != hishost; - host = hishost->q_forw) - /* hostm transfer remque's the host and - attaches it to the new server */ - hostm_transfer(host, limbo_server); - srv_nack_release(server); -} /* * Handle an ADMIN message from some random client. @@ -995,130 +832,131 @@ server_lost(server) /*ARGSUSED*/ Code_t server_adispatch(notice, auth, who, server) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - ZServerDesc_t *server; + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + Server *server; { - /* this had better be a HELLO message--start of acquisition - protocol, OR a status req packet */ + /* this had better be a HELLO message--start of acquisition + protocol, OR a status req packet */ + + if (strcmp(notice->z_opcode, ADMIN_STATUS) == 0) { + /* status packet */ + send_stats(who); + return ZERR_NONE; + } - if (!strcmp(notice->z_opcode, ADMIN_STATUS)) { - /* status packet */ - send_stats(who); - return(ZERR_NONE); - } #ifdef notdef - syslog(LOG_INFO, "disp: new server?"); - if (server_register(notice, auth, who) != ZERR_NONE) - syslog(LOG_INFO, "new server failed"); - else { - syslog(LOG_INFO, "new server %s, %d", - inet_ntoa(who->sin_addr), - ntohs(who->sin_port)); - hello_respond(who, DONT_ADJUST, auth); - } + syslog(LOG_INFO, "disp: new server?"); + if (server_register(notice, auth, who) != ZERR_NONE) { + syslog(LOG_INFO, "new server failed"); + } else { + syslog(LOG_INFO, "new server %s, %d", inet_ntoa(who->sin_addr), + ntohs(who->sin_port)); + hello_respond(who, DONT_ADJUST, auth); + } #else - syslog(LOG_INFO, "srv_adisp: server attempt from %s", - inet_ntoa(who->sin_addr)); + syslog(LOG_INFO, "srv_adisp: server attempt from %s", + inet_ntoa(who->sin_addr)); #endif /* notdef */ - return(ZERR_NONE); + + return ZERR_NONE; } static void send_stats(who) - struct sockaddr_in *who; + struct sockaddr_in *who; { - register int i; - char buf[BUFSIZ]; - char **responses; - int num_resp; - char *vers, *pkts, *upt; + int i; + char buf[BUFSIZ]; + char **responses; + int num_resp; + char *vers, *pkts, *upt; #if defined(OLD_COMPAT) || defined(NEW_COMPAT) - int extrafields = 0; + int extrafields = 0; #endif /* OLD_ or NEW_COMPAT */ #define NUM_FIXED 3 /* 3 fixed fields, plus server info */ /* well, not really...but for backward compatibility, we gotta do it this way. */ - vers = get_version(); + vers = get_version(); - (void) sprintf(buf, "%d pkts", npackets); - pkts = strsave(buf); - (void) sprintf(buf, "%d seconds operational",NOW - uptime); - upt = strsave(buf); + sprintf(buf, "%d pkts", npackets); + pkts = strsave(buf); + sprintf(buf, "%d seconds operational",NOW - uptime); + upt = strsave(buf); #ifdef OLD_COMPAT - if (old_compat_count_uloc) extrafields++; - if (old_compat_count_ulocate) extrafields++; - if (old_compat_count_subscr) extrafields++; + if (old_compat_count_uloc) + extrafields++; + if (old_compat_count_ulocate) + extrafields++; + if (old_compat_count_subscr) + extrafields++; #endif /* OLD_COMPAT */ #ifdef NEW_COMPAT - if (new_compat_count_uloc) extrafields++; - if (new_compat_count_subscr) extrafields++; + if (new_compat_count_uloc) + extrafields++; + if (new_compat_count_subscr) + extrafields++; #endif /* NEW_COMPAT */ #if defined(OLD_COMPAT) || defined(NEW_COMPAT) - responses = (char **) xmalloc((NUM_FIXED + nservers + extrafields) * - sizeof(char **)); + responses = (char **) malloc((NUM_FIXED + nservers + extrafields) * + sizeof(char *)); #else - responses = (char **) xmalloc ((NUM_FIXED + nservers) * - sizeof(char **)); + responses = (char **) malloc((NUM_FIXED + nservers) * sizeof(char *)); #endif /* OLD_ or NEW_COMPAT */ - responses[0] = vers; - responses[1] = pkts; - responses[2] = upt; - - num_resp = NUM_FIXED; - /* start at 1 and ignore limbo */ - for (i = 1; i < nservers ; i++) { - (void) sprintf(buf, "%s/%s%s", otherservers[i].addr, - srv_states[(int) otherservers[i].zs_state], - otherservers[i].zs_dumping ? " (DUMPING)" : ""); - responses[num_resp++] = strsave (buf); - } + responses[0] = vers; + responses[1] = pkts; + responses[2] = upt; + + num_resp = NUM_FIXED; + /* start at 1 and ignore limbo */ + for (i = 1; i < nservers ; i++) { + sprintf(buf, "%s/%s%s", otherservers[i].addr_str, + srv_states[(int) otherservers[i].state], + otherservers[i].dumping ? " (DUMPING)" : ""); + responses[num_resp++] = strsave(buf); + } #ifdef OLD_COMPAT - if (old_compat_count_uloc) { - (void) sprintf(buf, "%d old old location requests", - old_compat_count_uloc); - responses[num_resp++] = strsave (buf); - } - if (old_compat_count_ulocate) { - (void) sprintf(buf, "%d old old loc lookup requests", - old_compat_count_ulocate); - responses[num_resp++] = strsave (buf); - } - if (old_compat_count_subscr) { - (void) sprintf(buf, "%d old old subscr requests", - old_compat_count_subscr); - responses[num_resp++] = strsave (buf); - } + if (old_compat_count_uloc) { + sprintf(buf, "%d old old location requests", old_compat_count_uloc); + responses[num_resp++] = strsave(buf); + } + if (old_compat_count_ulocate) { + sprintf(buf, "%d old old loc lookup requests", + old_compat_count_ulocate); + responses[num_resp++] = strsave(buf); + } + if (old_compat_count_subscr) { + sprintf(buf, "%d old old subscr requests", old_compat_count_subscr); + responses[num_resp++] = strsave(buf); + } #endif /* OLD_COMPAT */ #ifdef NEW_COMPAT - if (new_compat_count_uloc) { - (void) sprintf(buf, "%d new old location requests", - new_compat_count_uloc); - responses[num_resp++] = strsave (buf); - } - if (new_compat_count_subscr) { - (void) sprintf(buf, "%d new old subscr requests", - new_compat_count_subscr); - responses[num_resp++] = strsave (buf); - } + if (new_compat_count_uloc) { + sprintf(buf, "%d new old location requests", new_compat_count_uloc); + responses[num_resp++] = strsave(buf); + } + if (new_compat_count_subscr) { + sprintf(buf, "%d new old subscr requests", new_compat_count_subscr); + responses[num_resp++] = strsave(buf); + } #endif /* NEW_COMPAT */ - send_msg_list(who, ADMIN_STATUS, responses, num_resp, 0, -1); - /* Start at one; don't try to free static version string */ - for (i = 1; i < num_resp; i++) - xfree(responses[i]); - xfree(responses); - return; + send_msg_list(who, ADMIN_STATUS, responses, num_resp, 0); + + /* Start at one; don't try to free static version string */ + for (i = 1; i < num_resp; i++) + free(responses[i]); + free(responses); } /* * Get a list of server addresses. -#ifdef HESIOD +#ifdef ZEPHYR_USES_HESIOD * This list is retrieved from Hesiod. #else * This list is read from a file. @@ -1129,46 +967,50 @@ send_stats(who) static struct in_addr * get_server_addrs(number) - int *number; /* RETURN */ + int *number; /* RETURN */ { - register int i; - char **server_hosts; - register char **cpp; - struct in_addr *addrs; - register struct in_addr *addr; - register struct hostent *hp; - -#ifdef HESIOD - /* get the names from Hesiod */ - if (!(server_hosts = hes_resolve("zephyr","sloc"))) - return((struct in_addr *)NULL); + int i; + char **server_hosts; + char **cpp; + struct in_addr *addrs; + struct in_addr *addr; + struct hostent *hp; + +#ifdef ZEPHYR_USES_HESIOD + /* get the names from Hesiod */ + server_hosts = hes_resolve("zephyr","sloc"); + if (!server_hosts) + return NULL; #else - if (!(server_hosts = get_server_list(SERVER_LIST_FILE))) - return((struct in_addr *)NULL); + server_hosts = get_server_list(list_file); + if (!server_hosts) + return NULL; #endif - /* count up */ - for (cpp = server_hosts, i = 0; *cpp; cpp++, i++); + /* count up */ + i = 0; + for (cpp = server_hosts; *cpp; cpp++) + i++; - addrs = (struct in_addr *) xmalloc(i * sizeof(struct in_addr)); - - /* Convert to in_addr's */ - for (cpp = server_hosts, addr = addrs, i = 0; *cpp; cpp++) { - hp = gethostbyname(*cpp); - if (hp) { - (void) memcpy((caddr_t) addr, (caddr_t)hp->h_addr, - sizeof(struct in_addr)); - addr++, i++; - } else - syslog(LOG_WARNING, "hostname failed, %s",*cpp); + addrs = (struct in_addr *) malloc(i * sizeof(struct in_addr)); + + /* Convert to in_addr's */ + for (cpp = server_hosts, addr = addrs, i = 0; *cpp; cpp++) { + hp = gethostbyname(*cpp); + if (hp) { + memcpy(addr, hp->h_addr, sizeof(struct in_addr)); + addr++, i++; + } else { + syslog(LOG_WARNING, "hostname failed, %s", *cpp); } - *number = i; -#ifndef HESIOD - free_server_list(server_hosts); + } + *number = i; +#ifndef ZEPHYR_USES_HESIOD + free_server_list(server_hosts); #endif - return(addrs); + return addrs; } -#ifndef HESIOD +#ifndef ZEPHYR_USES_HESIOD static int nhosts = 0; @@ -1179,40 +1021,46 @@ static int nhosts = 0; static char ** get_server_list(file) - char *file; + char *file; { - FILE *fp; - char buf[MAXHOSTNAMELEN]; - char **ret_list; - int nused = 0; - char *newline; - - if (!(fp = fopen(file, "r"))) - return((char **)0); - - /* start with 16, realloc if necessary */ - nhosts = 16; - ret_list = (char **)xmalloc(nhosts * sizeof(char *)); - + FILE *fp; + char buf[MAXHOSTNAMELEN]; + char **ret_list; + int nused = 0; + char *newline; + + /* start with 16, realloc if necessary */ + nhosts = 16; + ret_list = (char **) malloc(nhosts * sizeof(char *)); + + fp = fopen(file, "r"); + if (fp) { while (fgets(buf, MAXHOSTNAMELEN, fp)) { - /* nuke the newline, being careful not to overrun - the buffer searching for it with strlen() */ - buf[MAXHOSTNAMELEN - 1] = '\0'; - if (newline = index(buf, '\n')) - *newline = '\0'; - - if (nused+1 >= nhosts) { - /* get more pointer space if necessary */ - /* +1 to leave room for null pointer */ - ret_list = (char **)realloc((char *)ret_list, - (unsigned) nhosts * 2); - nhosts = nhosts * 2; - } - ret_list[nused++] = strsave (buf); - } - (void) fclose(fp); - ret_list[nused] = (char *)0; - return(ret_list); + /* nuke the newline, being careful not to overrun + the buffer searching for it with strlen() */ + buf[MAXHOSTNAMELEN - 1] = '\0'; + newline = strchr(buf, '\n'); + if (newline) + *newline = '\0'; + + if (nused + 1 >= nhosts) { + /* get more pointer space if necessary */ + /* +1 to leave room for null pointer */ + ret_list = (char **) realloc(ret_list, nhosts * 2); + nhosts = nhosts * 2; + } + ret_list[nused++] = strsave(buf); + } + fclose(fp); + } else { + if (gethostname(buf, sizeof(buf)) < 0) { + free(ret_list); + return NULL; + } + ret_list[nused++] = strsave(buf); + } + ret_list[nused] = NULL; + return ret_list; } /* @@ -1220,16 +1068,16 @@ get_server_list(file) */ static void free_server_list(list) - register char **list; + char **list; { - char **orig_list = list; + char **orig_list = list; - if (!nhosts) /* nothing allocated */ - return; - for (; *list; list++) - xfree(*list); - xfree(orig_list); + if (!nhosts) /* nothing allocated */ return; + for (; *list; list++) + free(*list); + free(orig_list); + return; } #endif @@ -1238,37 +1086,22 @@ free_server_list(list) * to go off immediately to send hello's to other servers. */ -STATIC void +static void setup_server(server, addr) - register ZServerDesc_t *server; - struct in_addr *addr; + Server *server; + struct in_addr *addr; { - register ZHostList_t *host; - - server->zs_state = SERV_DEAD; - server->zs_timeout = timo_dead; - server->zs_numsent = 0; - server->zs_addr.sin_family = AF_INET; - /* he listens to the same port we do */ - server->zs_addr.sin_port = sock_sin.sin_port; - server->zs_addr.sin_addr = *addr; - strcpy (server->addr, inet_ntoa (*addr)); - - /* set up a timer for this server */ - server->zs_timer = timer_set_rel(0L, server_timo, (void *) server); - host = (ZHostList_t *) xmalloc(sizeof(ZHostList_t)); - if (!host) { - /* unrecoverable */ - syslog(LOG_CRIT, "zs_host alloc"); - abort(); - } - host->q_forw = host->q_back = host; - server->zs_hosts = host; - - server->zs_update_queue = NULLZSPT; - server->zs_dumping = 0; - - return; + server->state = SERV_DEAD; + server->timeout = timo_dead; + server->num_hello_sent = 0; + server->addr.sin_family = AF_INET; + /* he listens to the same port we do */ + server->addr.sin_port = srv_addr.sin_port; + server->addr.sin_addr = *addr; + strcpy(server->addr_str, inet_ntoa(*addr)); + server->timer = timer_set_rel(0L, server_timo, server); + server->queue = NULL; + server->dumping = 0; } /* @@ -1277,62 +1110,61 @@ setup_server(server, addr) static void hello_respond(who, adj, auth) - struct sockaddr_in *who; - int adj; - int auth; + struct sockaddr_in *who; + int adj; + int auth; { - register ZServerDesc_t *which; + Server *which; #if 0 - zdbug((LOG_DEBUG, "hello from %s", inet_ntoa(who->sin_addr))); + zdbug((LOG_DEBUG, "hello from %s", inet_ntoa(who->sin_addr))); #endif - send_msg(who, ADMIN_IMHERE, auth); - if (adj != ADJUST) - return; - - /* If we think he's down, schedule an immediate HELLO. */ - - if (!(which = server_which_server(who))) - return; - - switch (which->zs_state) { - case SERV_DEAD: - /* he said hello, we thought he was dead. - reschedule his hello for now. */ - timer_reset(which->zs_timer); - which->zs_timer = timer_set_rel(0L, server_timo, - (void *) which); - break; - case SERV_STARTING: - case SERV_TARDY: - case SERV_UP: - default: - break; - } + send_msg(who, ADMIN_IMHERE, auth); + if (adj != ADJUST) + return; + + /* If we think he's down, schedule an immediate HELLO. */ + + which = server_which_server(who); + if (!which) return; + + switch (which->state) { + case SERV_DEAD: + /* he said hello, we thought he was dead. + reschedule his hello for now. */ + timer_reset(which->timer); + which->timer = timer_set_rel(0L, server_timo, which); + break; + case SERV_STARTING: + case SERV_TARDY: + case SERV_UP: + default: + break; + } } /* * return the server descriptor for server at who */ -ZServerDesc_t * +Server * server_which_server(who) - struct sockaddr_in *who; + struct sockaddr_in *who; { - register ZServerDesc_t *server; - register int i; + Server *server; + int i; - if (who->sin_port != sock_sin.sin_port) - return(NULLZSDT); + if (who->sin_port != srv_addr.sin_port) + return NULL; - /* don't check limbo */ - for (server = &otherservers[1], i = 1; i < nservers; i++, server++) { - if (server->zs_addr.sin_addr.s_addr == who->sin_addr.s_addr) - return(server); - } - return(NULLZSDT); + /* don't check limbo */ + for (server = &otherservers[1], i = 1; i < nservers; i++, server++) { + if (server->addr.sin_addr.s_addr == who->sin_addr.s_addr) + return server; + } + return NULL; } /* @@ -1341,52 +1173,50 @@ server_which_server(who) */ static void srv_responded(who) - struct sockaddr_in *who; + struct sockaddr_in *who; { - register ZServerDesc_t *which = server_which_server(who); + Server *which = server_which_server(who); #if 0 - zdbug((LOG_DEBUG, "srv_responded %s", inet_ntoa(who->sin_addr))); + zdbug((LOG_DEBUG, "srv_responded %s", inet_ntoa(who->sin_addr))); #endif - if (!which) { - syslog(LOG_ERR, "hello input from non-server?!"); - return; - } + if (!which) { + syslog(LOG_ERR, "hello input from non-server?!"); + return; + } - switch (which->zs_state) { - case SERV_DEAD: - /* he responded, we thought he was dead. mark as starting - and negotiate */ - which->zs_state = SERV_STARTING; - which->zs_timeout = timo_tardy; - timer_reset(which->zs_timer); - which->zs_timer = timer_set_rel(0L, server_timo, - (void *) which); - - case SERV_STARTING: - /* here we negotiate and set up a braindump */ - if (bdump_socket < 0) { - /* XXX offer it to the other server */ - bdump_offer(who); - } - break; - case SERV_TARDY: - which->zs_state = SERV_UP; - case SERV_UP: - /* reset the timer and counts */ - which->zs_numsent = 0; - which->zs_timeout = timo_up; - timer_reset(which->zs_timer); - which->zs_timer = timer_set_rel(which->zs_timeout, server_timo, - (void *) which); - break; - } + switch (which->state) { + case SERV_DEAD: + /* he responded, we thought he was dead. mark as starting + and negotiate */ + which->state = SERV_STARTING; + which->timeout = timo_tardy; + timer_reset(which->timer); + which->timer = timer_set_rel(0L, server_timo, which); + + case SERV_STARTING: + /* here we negotiate and set up a braindump */ + if (bdump_socket < 0) + bdump_offer(who); + break; + + case SERV_TARDY: + which->state = SERV_UP; + /* Fall through. */ + + case SERV_UP: + /* reset the timer and counts */ + which->num_hello_sent = 0; + which->timeout = timo_up; + timer_reset(which->timer); + which->timer = timer_set_rel(which->timeout, server_timo, which); + break; + } #if 0 - zdbug((LOG_DEBUG, "srv %s is %s", which->addr, - srv_states[(int) which->zs_state])); + zdbug((LOG_DEBUG, "srv %s is %s", which->addr_str, + srv_states[which->state])); #endif - return; } /* @@ -1396,13 +1226,11 @@ srv_responded(who) void server_shutdown() { - register int i; + int i; - /* don't tell limbo to go away, start at 1*/ - for (i = 1; i < nservers; i++) { - send_msg(&otherservers[i].zs_addr, ADMIN_SHUTDOWN, 1); - } - return; + /* don't tell limbo to go away, start at 1*/ + for (i = 1; i < nservers; i++) + send_msg(&otherservers[i].addr, ADMIN_SHUTDOWN, 1); } /* @@ -1412,54 +1240,50 @@ server_shutdown() static void send_msg(who, opcode, auth) - struct sockaddr_in *who; - char *opcode; - int auth; + struct sockaddr_in *who; + char *opcode; + int auth; { - ZNotice_t notice; - register ZNotice_t *pnotice; /* speed hack */ - char *pack; - int packlen; - Code_t retval; - - pnotice = ¬ice; - - pnotice->z_kind = ACKED; - - pnotice->z_port = sock_sin.sin_port; - pnotice->z_class = ZEPHYR_ADMIN_CLASS; - pnotice->z_class_inst = ""; - pnotice->z_opcode = opcode; - pnotice->z_sender = myname; /* myname is the hostname */ - pnotice->z_recipient = ""; - pnotice->z_default_format = ""; - pnotice->z_message = (caddr_t) NULL; - pnotice->z_message_len = 0; - pnotice->z_num_other_fields = 0; - - /* XXX for now, we don't do authentication */ - auth = 0; - - if ((retval = ZFormatNotice(pnotice, &pack, &packlen, - auth ? ZAUTH : ZNOAUTH)) != ZERR_NONE) { - syslog(LOG_WARNING, "snd_msg format: %s", - error_message(retval)); - return; - } - if ((retval = ZSetDestAddr(who)) != ZERR_NONE) { - syslog(LOG_WARNING, "snd_msg set addr: %s", - error_message(retval)); - xfree(pack); /* free allocated storage */ - return; - } - /* don't wait for ack */ - if ((retval = ZSendPacket(pack, packlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "snd_msg xmit: %s", error_message(retval)); - xfree(pack); /* free allocated storage */ - return; - } - xfree(pack); /* free allocated storage */ + ZNotice_t notice; + ZNotice_t *pnotice; /* speed hack */ + char *pack; + int packlen; + Code_t retval; + + pnotice = ¬ice; + + pnotice->z_kind = ACKED; + + pnotice->z_port = srv_addr.sin_port; + pnotice->z_class = ZEPHYR_ADMIN_CLASS; + pnotice->z_class_inst = ""; + pnotice->z_opcode = opcode; + pnotice->z_sender = myname; /* myname is the hostname */ + pnotice->z_recipient = ""; + pnotice->z_default_format = ""; + pnotice->z_message = NULL; + pnotice->z_message_len = 0; + pnotice->z_num_other_fields = 0; + + /* XXX for now, we don't do authentication */ + auth = 0; + + retval = ZFormatNotice(pnotice, &pack, &packlen, auth ? ZAUTH : ZNOAUTH); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "snd_msg format: %s", error_message(retval)); + return; + } + retval = ZSetDestAddr(who); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "snd_msg set addr: %s", error_message(retval)); + free(pack); return; + } + /* don't wait for ack */ + retval = ZSendPacket(pack, packlen, 0); + if (retval != ZERR_NONE) + syslog(LOG_WARNING, "snd_msg xmit: %s", error_message(retval)); + free(pack); } /* @@ -1471,83 +1295,48 @@ send_msg(who, opcode, auth) */ static void -send_msg_list(who, opcode, lyst, num, auth, server_idx) - struct sockaddr_in *who; - char *opcode; - char **lyst; - int num; - int auth; - int server_idx; +send_msg_list(who, opcode, lyst, num, auth) + struct sockaddr_in *who; + char *opcode; + char **lyst; + int num; + int auth; { - ZNotice_t notice; - register ZNotice_t *pnotice; /* speed hack */ - char *pack; - int packlen; - Code_t retval; - register ZNotAcked_t *nacked; - - pnotice = ¬ice; - - pnotice->z_kind = UNSAFE; - - pnotice->z_port = sock_sin.sin_port; - pnotice->z_class = ZEPHYR_ADMIN_CLASS; - pnotice->z_class_inst = ""; - pnotice->z_opcode = opcode; - pnotice->z_sender = myname; /* myname is the hostname */ - pnotice->z_recipient = ""; - pnotice->z_default_format = ""; - pnotice->z_message = (caddr_t) NULL; - pnotice->z_message_len = 0; - pnotice->z_num_other_fields = 0; - - /* XXX for now, we don't do authentication */ - auth = 0; - - retval = ZFormatNoticeList (pnotice, lyst, num, &pack, &packlen, - auth ? ZAUTH : ZNOAUTH); - if (retval != ZERR_NONE) { - syslog(LOG_WARNING, "snd_msg_lst format: %s", - error_message(retval)); - return; - } - if ((retval = ZSetDestAddr(who)) != ZERR_NONE) { - syslog(LOG_WARNING, "snd_msg_lst set addr: %s", - error_message(retval)); - xfree(pack); /* free allocated storage */ - return; - } - if ((retval = ZSendPacket(pack, packlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "snd_msg_lst xmit: %s", error_message(retval)); - xfree(pack); /* free allocated storage */ - return; - } - - if (!(nacked = (ZNotAcked_t *)xmalloc(sizeof(ZNotAcked_t)))) { - /* no space: just punt */ - syslog(LOG_WARNING, "xmit nack malloc"); - xfree(pack); - return; - } - - nacked->na_rexmits = 0; - nacked->na_packet = pack; - nacked->na_packsz = packlen; - nacked->na_uid = pnotice->z_uid; - nacked->q_forw = nacked->q_back = nacked; - nacked->na_abstimo = NOW + abs_timo; - - /* Set the address and chain into the appropriate queue. */ - if (server_idx < 0) { - nacked->na_addr = *who; - nacked->na_timer = timer_set_rel(rexmit_secs, rexmit, nacked); - xinsque(nacked, nacklist); - } else { - nacked->na_srv_idx = server_idx; - nacked->na_timer = timer_set_rel(srv_rexmit_secs, srv_rexmit, - nacked); - xinsque(nacked, srv_nacklist); - } + ZNotice_t notice; + char *pack; + int packlen; + Code_t retval; + Unacked *nacked; + + notice.z_kind = UNSAFE; + notice.z_port = srv_addr.sin_port; + notice.z_class = ZEPHYR_ADMIN_CLASS; + notice.z_class_inst = ""; + notice.z_opcode = opcode; + notice.z_sender = myname; /* myname is the hostname */ + notice.z_recipient = ""; + notice.z_default_format = ""; + notice.z_message = NULL; + notice.z_message_len = 0; + notice.z_num_other_fields = 0; + + /* XXX for now, we don't do authentication */ + auth = 0; + + retval = ZFormatNoticeList(¬ice, lyst, num, &pack, &packlen, + auth ? ZAUTH : ZNOAUTH); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "snd_msg_lst format: %s", error_message(retval)); + return; + } + retval = ZSetDestAddr(who); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "snd_msg_lst set addr: %s", error_message(retval)); + free(pack); + return; + } + xmit_frag(¬ice, pack, packlen, 0); + free(pack); } /* @@ -1556,125 +1345,116 @@ send_msg_list(who, opcode, lyst, num, auth, server_idx) /*ARGSUSED*/ void server_forward(notice, auth, who) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; { - register int i; - caddr_t pack; - int packlen; - Code_t retval; + int i; + caddr_t pack; + int packlen; + Code_t retval; #if 0 - zdbug((LOG_DEBUG, "srv_forw")); + zdbug((LOG_DEBUG, "srv_forw")); #endif - /* don't send to limbo */ - for (i = 1; i < nservers; i++) { - if (i == me_server_idx) /* don't xmit to myself */ - continue; - if (otherservers[i].zs_state == SERV_DEAD && - otherservers[i].zs_dumping == 0) - /* if we are dumping to him, we want to - queue it, even if he's dead */ - continue; - - if (!(pack = (caddr_t) xmalloc(sizeof(ZPacket_t)))) { - syslog(LOG_CRIT, "srv_fwd malloc"); - abort(); - } - if ((retval = ZFormatSmallRawNotice(notice, pack, &packlen)) != ZERR_NONE) { - syslog(LOG_WARNING, "srv_fwd format: %s", - error_message(retval)); - continue; - } - if (otherservers[i].zs_dumping) { - server_queue(&(otherservers[i]), packlen, pack, - auth, who); - continue; - } - server_forw_reliable(&otherservers[i], pack, packlen, notice); + /* don't send to limbo */ + for (i = 1; i < nservers; i++) { + if (i == me_server_idx) /* don't xmit to myself */ + continue; + if (otherservers[i].state == SERV_DEAD && + otherservers[i].dumping == 0) { + /* if we are dumping to him, we want to + queue it, even if he's dead */ + continue; + } + + pack = malloc(sizeof(ZPacket_t)); + if (!pack) { + syslog(LOG_CRIT, "srv_fwd malloc"); + abort(); + } + retval = ZFormatSmallRawNotice(notice, pack, &packlen); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "srv_fwd format: %s", error_message(retval)); + continue; } - return; + if (otherservers[i].dumping) { + server_queue(&otherservers[i], packlen, pack, auth, who); + continue; + } + server_forw_reliable(&otherservers[i], pack, packlen, notice); + } } -STATIC void +static void server_forw_reliable(server, pack, packlen, notice) - ZServerDesc_t *server; - caddr_t pack; - int packlen; - ZNotice_t *notice; + Server *server; + caddr_t pack; + int packlen; + ZNotice_t *notice; { - Code_t retval; - register ZNotAcked_t *nacked; - - if ((retval = ZSetDestAddr(&server->zs_addr)) != ZERR_NONE) { - syslog(LOG_WARNING, "srv_fwd_rel set addr: %s", - error_message(retval)); - xfree(pack); - return; - } - if ((retval = ZSendPacket(pack, packlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "srv_fwd xmit: %s", error_message(retval)); - xfree(pack); - return; - } - /* now we've sent it, mark it as not ack'ed */ + Code_t retval; + Unacked *nacked; + int hashval; + + retval = ZSetDestAddr(&server->addr); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "srv_fwd_rel set addr: %s", error_message(retval)); + free(pack); + return; + } + retval = ZSendPacket(pack, packlen, 0); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "srv_fwd xmit: %s", error_message(retval)); + free(pack); + return; + } + /* now we've sent it, mark it as not ack'ed */ - if (!(nacked = (ZNotAcked_t *)xmalloc(sizeof(ZNotAcked_t)))) { - /* no space: just punt */ - syslog(LOG_ERR, "srv_forw_rel nack malloc"); - xfree(pack); - return; - } - - nacked->na_rexmits = 0; - nacked->na_packet = pack; - nacked->na_srv_idx = server - otherservers; - nacked->na_packsz = packlen; - nacked->na_uid = notice->z_uid; - nacked->q_forw = nacked->q_back = nacked; - nacked->na_abstimo = 0; - - /* set a timer to retransmit */ - nacked->na_timer = timer_set_rel(srv_rexmit_secs, - srv_rexmit, - (void *) nacked); - /* chain in */ - xinsque(nacked, srv_nacklist); + nacked = (Unacked *) malloc(sizeof(Unacked)); + if (!nacked) { + /* no space: just punt */ + syslog(LOG_ERR, "srv_forw_rel nack malloc"); + free(pack); return; + } + + nacked->rexmits = 0; + nacked->packet = pack; + nacked->dest.srv_idx = server - otherservers; + nacked->packsz = packlen; + nacked->uid = notice->z_uid; + nacked->timer = timer_set_rel(rexmit_times[0], srv_rexmit, nacked); + hashval = SRV_NACKTAB_HASHVAL(nacked->dest.srv_idx, nacked->uid); + LIST_INSERT(&srv_nacktab[hashval], nacked); } -#ifdef CONCURRENT /* * send the queued message for the server. */ void server_send_queue(server) - ZServerDesc_t *server; + Server *server; { - register ZSrvPending_t *pending; - ZNotice_t notice; - Code_t status; - - while(server->zs_update_queue) { - pending = server_dequeue(server); - if ((status = ZParseNotice(pending->pend_packet, - pending->pend_len, - ¬ice)) != ZERR_NONE) { - syslog(LOG_ERR, - "ssq bad notice parse (%s): %s", - inet_ntoa(pending->pend_who.sin_addr), - error_message(status)); - } else { - server_forw_reliable(server, pending->pend_packet, - pending->pend_len, ¬ice); - xfree(pending); - /* ACK handling routines will free the packet */ - } + Pending *pending; + ZNotice_t notice; + Code_t status; + + while (server->queue) { + pending = server_dequeue(server); + status = ZParseNotice(pending->packet, pending->len, ¬ice); + if (status != ZERR_NONE) { + syslog(LOG_ERR, "ssq bad notice parse (%s): %s", + inet_ntoa(pending->who.sin_addr), error_message(status)); + } else { + server_forw_reliable(server, pending->packet, pending->len, + ¬ice); + free(pending); + /* ACK handling routines will free the packet */ } + } } -#endif /* * a server has acknowledged a message we sent to him; remove it from @@ -1683,82 +1463,75 @@ server_send_queue(server) static void srv_nack_cancel(notice, who) - register ZNotice_t *notice; - struct sockaddr_in *who; + ZNotice_t *notice; + struct sockaddr_in *who; { - register ZServerDesc_t *which = server_which_server(who); - register ZNotAcked_t *nacked; + Server *server = server_which_server(who); + Unacked *nacked; + int hashval; - if (!which) { - syslog(LOG_ERR, "non-server ack?"); - return; + if (!server) { + syslog(LOG_ERR, "non-server ack?"); + return; + } + hashval = SRV_NACKTAB_HASHVAL(server - otherservers, notice->z_uid); + for (nacked = srv_nacktab[hashval]; nacked; nacked = nacked->next) { + if (nacked->dest.srv_idx == server - otherservers + && ZCompareUID(&nacked->uid, ¬ice->z_uid)) { + timer_reset(nacked->timer); + free(nacked->packet); + LIST_DELETE(nacked); + free(nacked); + return; } - for (nacked = srv_nacklist->q_forw; - nacked != srv_nacklist; - nacked = nacked->q_forw) - if (&otherservers[nacked->na_srv_idx] == which) - if (ZCompareUID(&nacked->na_uid, ¬ice->z_uid)) { - timer_reset(nacked->na_timer); - xfree(nacked->na_packet); - xremque(nacked); - xfree(nacked); - return; - } + } #if 0 - zdbug((LOG_DEBUG, "srv_nack not found")); + zdbug((LOG_DEBUG, "srv_nack not found")); #endif - return; } /* * retransmit a message to another server */ -STATIC void -#ifdef __STDC__ -srv_rexmit(void *arg) -#else +static void srv_rexmit(arg) - void *arg; -#endif + void *arg; { - ZNotAcked_t *nackpacket = (ZNotAcked_t *) arg; - Code_t retval; - /* retransmit the packet */ + Unacked *packet = (Unacked *) arg; + Code_t retval; + /* retransmit the packet */ #if 0 - zdbug((LOG_DEBUG,"srv_rexmit to %s/%d", - otherservers[nackpacket->na_srv_idx].addr, - ntohs(otherservers[nackpacket->na_srv_idx].zs_addr.sin_port))); + zdbug((LOG_DEBUG,"srv_rexmit to %s/%d", + otherservers[packet->dest.srv_idx].addr_str, + ntohs(otherservers[packet->dest.srv_idx].addr.sin_port))); #endif - if (otherservers[nackpacket->na_srv_idx].zs_state == SERV_DEAD) { + if (otherservers[packet->dest.srv_idx].state == SERV_DEAD) { #if 0 - zdbug((LOG_DEBUG, "cancelling send to dead server")); + zdbug((LOG_DEBUG, "cancelling send to dead server")); #endif - xremque(nackpacket); - xfree(nackpacket->na_packet); - srv_nack_release(&otherservers[nackpacket->na_srv_idx]); - xfree(nackpacket); - return; - } - retval = ZSetDestAddr(&otherservers[nackpacket->na_srv_idx].zs_addr); - if (retval != ZERR_NONE) { - syslog(LOG_WARNING, "srv_rexmit set addr: %s", - error_message(retval)); - goto requeue; - - } - if ((retval = ZSendPacket(nackpacket->na_packet, - nackpacket->na_packsz, 0)) != ZERR_NONE) - syslog(LOG_WARNING, "srv_rexmit xmit: %s", - error_message(retval)); - -requeue: - /* reset the timer */ - nackpacket->na_timer = timer_set_rel(srv_rexmit_secs, - srv_rexmit, - (void *) nackpacket); + LIST_DELETE(packet); + free(packet->packet); + srv_nack_release(&otherservers[packet->dest.srv_idx]); + free(packet); return; + } + retval = ZSetDestAddr(&otherservers[packet->dest.srv_idx].addr); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "srv_rexmit set addr: %s", error_message(retval)); + } else { + retval = ZSendPacket(packet->packet, packet->packsz, 0); + if (retval != ZERR_NONE) + syslog(LOG_WARNING, "srv_rexmit xmit: %s", + error_message(retval)); + } + + /* reset the timer */ + if (rexmit_times[packet->rexmits + 1] != -1) + packet->rexmits++; + packet->timer = timer_set_rel(rexmit_times[packet->rexmits], srv_rexmit, + packet); } /* @@ -1768,29 +1541,22 @@ requeue: static void srv_nack_release(server) - ZServerDesc_t *server; + Server *server; { - /* XXX release any private queue for this server */ - - register ZNotAcked_t *nacked, *nack2; - - /* search the not-yet-acked list for anything destined to him, and - flush it. */ - for (nacked = srv_nacklist->q_forw; - nacked != srv_nacklist;) - if (&otherservers[nacked->na_srv_idx] == server) { - /* go back, since remque will change things */ - nack2 = nacked->q_back; - timer_reset(nacked->na_timer); - xremque(nacked); - xfree(nacked->na_packet); - xfree(nacked); - /* now that the remque adjusted the linked list, - we go forward again */ - nacked = nack2->q_forw; - } else - nacked = nacked->q_forw; - return; + int i; + Unacked *nacked, *next; + + for (i = 0; i < SRV_NACKTAB_HASHSIZE; i++) { + for (nacked = srv_nacktab[i]; nacked; nacked = next) { + next = nacked->next; + if (nacked->dest.srv_idx == server - otherservers) { + timer_reset(nacked->timer); + LIST_DELETE(nacked); + free(nacked->packet); + free(nacked); + } + } + } } /* @@ -1800,23 +1566,24 @@ srv_nack_release(server) static void srv_nack_renumber (new_idx) - register int* new_idx; + int *new_idx; { /* XXX release any private queue for this server */ - - register ZNotAcked_t *nacked; + Unacked *nacked; + int idx, i; /* search the not-yet-acked list for anything destined to 'from', and change the index to 'to'. */ - for (nacked = srv_nacklist->q_forw; nacked != srv_nacklist;) { - int idx = new_idx[nacked->na_srv_idx]; - if (idx < 0) { - syslog (LOG_ERR, - "srv_nack_renumber error: [%d]=%d", - nacked->na_srv_idx, idx); - idx = 0; + for (i = 0; i < SRV_NACKTAB_HASHSIZE; i++) { + for (nacked = srv_nacktab[i]; nacked; nacked = nacked->next) { + idx = new_idx[nacked->dest.srv_idx]; + if (idx < 0) { + syslog(LOG_ERR, "srv_nack_renumber error: [%d]=%d", + nacked->dest.srv_idx, idx); + idx = 0; + } + nacked->dest.srv_idx = idx; } - nacked->na_srv_idx = idx; } } @@ -1825,58 +1592,47 @@ srv_nack_renumber (new_idx) */ static void server_queue(server, len, pack, auth, who) - ZServerDesc_t *server; - int len; - caddr_t pack; - int auth; - struct sockaddr_in *who; + Server *server; + int len; + void *pack; + int auth; + struct sockaddr_in *who; { - register ZSrvPending_t *pending; - - if (!server->zs_update_queue) { - if (!(pending = - (ZSrvPending_t *)xmalloc(sizeof(ZSrvPending_t)))) { - syslog(LOG_CRIT, "zs_update_queue head malloc"); - abort(); - } - pending->q_forw = pending->q_back = pending; - server->zs_update_queue = pending; - } - if (!(pending = (ZSrvPending_t *)xmalloc(sizeof(ZSrvPending_t)))) { - syslog(LOG_CRIT, "zs_update_queue malloc"); - abort(); - } - pending->pend_packet = pack; - pending->pend_len = len; - pending->pend_auth = auth; - pending->pend_who = *who; + Pending *pending; - /* put it on the end of the list */ - xinsque(pending, server->zs_update_queue->q_back); - return; + pending = (Pending *) malloc(sizeof(Pending)); + if (!pending) { + syslog(LOG_CRIT, "update_queue malloc"); + abort(); + } + pending->packet = pack; + pending->len = len; + pending->auth = auth; + pending->who = *who; + pending->next = NULL; + + /* put it on the end of the list */ + if (server->queue) + server->queue_last->next = pending; + else + server->queue = server->queue_last = pending; } /* * Pull a notice off the hold queue. */ -ZSrvPending_t * +Pending * server_dequeue(server) - register ZServerDesc_t *server; + Server *server; { - ZSrvPending_t *pending; + Pending *pending; - if (!server->zs_update_queue) - return(NULLZSPT); - pending = server->zs_update_queue->q_forw; - /* pull it off */ - xremque(pending); - if (server->zs_update_queue->q_forw == server->zs_update_queue) { - /* empty queue now */ - xfree(server->zs_update_queue); - server->zs_update_queue = NULLZSPT; - } - return(pending); + if (!server->queue) + return NULL; + pending = server->queue; + server->queue = pending->next; + return pending; } /* @@ -1885,38 +1641,34 @@ server_dequeue(server) void server_pending_free(pending) - register ZSrvPending_t *pending; + Pending *pending; { - xfree(pending->pend_packet); - xfree(pending); - return; + free(pending->packet); + free(pending); + return; } -#ifdef CONCURRENT /* * Queue something to be handled later by this server. */ void server_self_queue(notice, auth, who) - ZNotice_t* notice; - int auth; - struct sockaddr_in * who; + ZNotice_t* notice; + int auth; + struct sockaddr_in * who; { - caddr_t pack; - int packlen; - Code_t retval; - - if ((retval = ZFormatRawNotice(notice, &pack, &packlen)) - != ZERR_NONE) { - syslog(LOG_CRIT, "srv_self_queue format: %s", - error_message(retval)); - abort(); - } - server_queue(me_server, packlen, pack, auth, who); - return; + char *pack; + int packlen; + Code_t retval; + + retval = ZFormatRawNotice(notice, &pack, &packlen); + if (retval != ZERR_NONE) { + syslog(LOG_CRIT, "srv_self_queue format: %s", error_message(retval)); + abort(); + } + server_queue(me_server, packlen, pack, auth, who); } -#endif /* * dump info about servers onto the fp. @@ -1925,16 +1677,14 @@ server_self_queue(notice, auth, who) */ void server_dump_servers(fp) - FILE *fp; + FILE *fp; { - register int i; - - for (i = 0; i < nservers ; i++) { - (void) fprintf(fp, "%d:%s/%s%s\n", - i, otherservers[i].addr, - srv_states[(int) otherservers[i].zs_state], - otherservers[i].zs_dumping ? " (DUMPING)" : ""); - } + int i; - return; + for (i = 0; i < nservers ; i++) { + fprintf(fp, "%d:%s/%s%s\n", i, otherservers[i].addr_str, + srv_states[otherservers[i].state], + otherservers[i].dumping ? " (DUMPING)" : ""); + } } + diff --git a/server/subscr.c b/server/subscr.c index 742adda..c305c70 100644 --- a/server/subscr.c +++ b/server/subscr.c @@ -12,10 +12,11 @@ */ #include <zephyr/mit-copyright.h> +#include "zserver.h" #ifndef lint #ifndef SABER -static char rcsid_subscr_c[] = "$Id$"; +static const char rcsid_subscr_c[] = "$Id$"; #endif #endif @@ -25,7 +26,7 @@ static char rcsid_subscr_c[] = "$Id$"; * External functions: * * Code_t subscr_subscribe(who, notice) - * ZClient_t *who; + * Client *who; * ZNotice_t *notice; * * Code_t subscr_cancel(sin, notice) @@ -33,16 +34,16 @@ static char rcsid_subscr_c[] = "$Id$"; * ZNotice_t *notice; * * Code_t subscr_cancel_client(client) - * ZClient_t *client; + * Client *client; * * Code_t subscr_cancel_host(addr) * struct in_addr *addr; * - * ZClientList_t *subscr_match_list(notice) + * Client *subscr_match_list(notice) * ZNotice_t *notice; * * void subscr_free_list(list) - * ZClientList_t *list; + * Client *list; * * void subscr_sendlist(notice, auth, who) * ZNotice_t *notice; @@ -50,28 +51,17 @@ static char rcsid_subscr_c[] = "$Id$"; * struct sockaddr_in *who; * * Code_t subscr_send_subs(client, vers) - * ZClient_t *client; + * Client *client; * char *vers; * * Code_t subscr_def_subs(who) - * ZClient_t *who; + * Client *who; * * void subscr_reset(); * */ -#include "zserver.h" -#include <ctype.h> -#include <strings.h> -#include <sys/stat.h> - -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -#ifdef KERBEROS +#ifdef ZEPHYR_USES_KERBEROS #ifndef NOENCRYPTION C_Block serv_key; Sched serv_ksched; @@ -83,36 +73,41 @@ Sched serv_ksched; #ifdef OLD_COMPAT #define OLD_ZEPHYR_VERSION "ZEPH0.0" #define OLD_CLIENT_INCOMPSUBS "INCOMP" -static void old_compat_subscr_sendlist P((ZNotice_t *notice, int auth, +static void old_compat_subscr_sendlist __P((ZNotice_t *notice, int auth, struct sockaddr_in *who)); extern int old_compat_count_subscr; /* counter of old use */ #endif /* OLD_COMPAT */ #ifdef NEW_COMPAT #define NEW_OLD_ZEPHYR_VERSION "ZEPH0.1" -static void new_old_compat_subscr_sendlist P((ZNotice_t *notice, int auth, +static void new_old_compat_subscr_sendlist __P((ZNotice_t *notice, int auth, struct sockaddr_in *who)); extern int new_compat_count_subscr; /* counter of old use */ #endif /* NEW_COMPAT */ extern char *re_comp(), *re_conv(); -static Code_t add_subscriptions P((ZClient_t *who, ZSubscr_t *subs_queue, +static Code_t add_subscriptions __P((Client *who, Destlist *subs_queue, ZNotice_t *notice)); -static ZSubscr_t *extract_subscriptions P((register ZNotice_t *notice)); -static void free_subscriptions P((register ZSubscr_t *subs)); -static char **subscr_marshal_subs P((ZNotice_t *notice, int auth, +static Destlist *extract_subscriptions __P((ZNotice_t *notice)); +static void free_subscriptions __P((Destlist *subs)); +static char **subscr_marshal_subs __P((ZNotice_t *notice, int auth, struct sockaddr_in *who, - register int *found)); -static ZSubscr_t *subscr_copy_def_subs P((char *person)); -static int cl_match P((ZSubscr_t*, ZClient_t *)); + int *found)); +static Destlist *subscr_copy_def_subs __P((char *person)); +static Code_t subscr_subscribe_realms __P((struct sockaddr_in *who, + Destlist *newsubs, + ZNotice_t *notice)); +static Code_t subscr_realm_sendit __P((Client *who, Destlist *subs, + ZNotice_t *notice, Realm *realm)); +static void subscr_unsub_realms __P((Destlist *newsubs)); +static void subscr_unsub_sendit __P((Destlist *subs, Realm *realm)); +static int cl_match __P((Destlist*, Client *)); static int defaults_read = 0; /* set to 1 if the default subs are in memory */ static ZNotice_t default_notice; /* contains default subscriptions */ -#undef P - -ZSTRING *wildcard_instance; -ZSTRING *empty; +String *wildcard_instance; +String *empty; /* WARNING: make sure this is the same as the number of strings you */ /* plan to hand back to the user in response to a subscription check, */ @@ -125,105 +120,89 @@ ZSTRING *empty; Code_t subscr_subscribe(who, notice) - ZClient_t *who; - ZNotice_t *notice; + Client *who; + ZNotice_t *notice; { - ZSubscr_t *subs_queue, *sub; - Code_t retval; - - if (!who->zct_subs) { - /* allocate a subscription head */ - sub = (ZSubscr_t *) xmalloc(sizeof(ZSubscr_t)); - if (!sub) - return(ENOMEM); - sub->q_forw = sub->q_back = sub; - sub->zst_dest.classname = sub->zst_dest.inst = - sub->zst_dest.recip = NULL; - who->zct_subs = sub; - } + Destlist *subs; - subs_queue = extract_subscriptions(notice); - return(add_subscriptions(who, subs_queue, notice)); + subs = extract_subscriptions(notice); + return add_subscriptions(who, subs, notice); } static Code_t -add_subscriptions(who, subs_queue, notice) - ZClient_t *who; - ZSubscr_t *subs_queue; - ZNotice_t *notice; +add_subscriptions(who, subs, notice) + Client *who; + Destlist *subs; + ZNotice_t *notice; { - ZSubscr_t *sub, *next; - Code_t retval; - ZAcl_t *acl; - ZSTRING *sender; - - if (!subs_queue) - return(ZERR_NONE); /* no subscr -> no error */ + Destlist *next; + Code_t retval; + Acl *acl; + String *sender; + Realm *realm = NULL; - sender = make_zstring(notice->z_sender,0); + if (!subs) + return ZERR_NONE; /* no subscr -> no error */ - START_CRITICAL_CODE; - - /* Loop over the new subscriptions. */ - next = subs_queue->q_forw; - while (next != subs_queue) { - sub = next; - next = sub->q_forw; + sender = make_string(notice->z_sender, 0); + /* Loop over the new subscriptions. */ + for (; subs; subs = next) { + next = subs->next; #if 0 - zdbug ((LOG_DEBUG, "subscr: %s/%s/%s", - sub->zst_dest.classname->string, - sub->zst_dest.inst->string, - sub->zst_dest.recip->string)); + zdbug ((LOG_DEBUG, "subscr: %s/%s/%s", subs->dest.classname->string, + subs->dest.inst->string, subs->dest.recip->string)); #endif - - if (!bdumping) { - if ((sub->zst_dest.recip != empty) - && (sub->zst_dest.recip != sender)) { - syslog(LOG_WARNING, "subscr unauth %s recipient %s", - sender->string, - sub->zst_dest.recip->string); + if (!bdumping) { + if (subs->dest.recip != empty && subs->dest.recip != sender + && subs->dest.recip->string[0] != '@') { + syslog(LOG_WARNING, "subscr unauth %s recipient %s", + sender->string, subs->dest.recip->string); + continue; + } + acl = class_get_acl(subs->dest.classname); + if (acl) { + if (!access_check(sender->string, acl, SUBSCRIBE)) { + syslog(LOG_WARNING, "subscr unauth %s class %s", + sender->string, subs->dest.classname->string); + continue; /* the for loop */ + } + if (wildcard_instance == subs->dest.inst) { + if (!access_check(sender->string, acl, INSTWILD)) { + syslog(LOG_WARNING, + "subscr unauth %s class %s wild inst", + sender->string, subs->dest.classname->string); continue; } - acl = class_get_acl(sub->zst_dest.classname); - if (acl) { - if (!(access_check(sender->string, acl, SUBSCRIBE))) { - syslog(LOG_WARNING, - "subscr unauth %s class %s", - sender->string, - sub->zst_dest.classname->string); - continue; /* the for loop */ - } - if (wildcard_instance == sub->zst_dest.inst) { - if (!access_check(sender->string, acl, INSTWILD)) { - syslog(LOG_WARNING, - "subscr unauth %s class %s wild inst", - notice->z_sender, - sub->zst_dest.classname->string); - continue; - } - } - } } - xremque(sub); - retval = triplet_register(who, &sub->zst_dest); - if (retval != ZERR_NONE) { - xfree(sub); - if (retval == ZSRV_CLASSXISTS) { - continue; - } else { - free_subscriptions(subs_queue); - END_CRITICAL_CODE; - return(retval); - } - } - xinsque(sub, who->zct_subs); + } } + /* check the recipient for a realm which isn't ours */ + realm = NULL; + if (subs->dest.recip->string[0] == '@' && + strcmp((subs->dest.recip->string + 1), ZGetRealm()) != 0) + realm = realm_get_realm_by_name(subs->dest.recip->string + 1); + if (realm) { + retval = subscr_realm_sendit(who, subs, notice, realm); + if (retval != ZERR_NONE) { + free(subs); + return(retval); + } + } + retval = triplet_register(who, &subs->dest, realm); + if (retval != ZERR_NONE) { + free(subs); + if (retval == ZSRV_CLASSXISTS) { + continue; + } else { + free_subscriptions(next); + return retval; + } + } + LIST_INSERT(&who->subs, subs); + } - END_CRITICAL_CODE; - - free_subscriptions(subs_queue); - return(ZERR_NONE); + return ZERR_NONE; } /* @@ -232,126 +211,101 @@ add_subscriptions(who, subs_queue, notice) Code_t subscr_def_subs(who) - ZClient_t *who; + Client *who; { - ZSubscr_t *subs; - - if (!who->zct_subs) { - /* allocate a subscription head */ - if (!(subs = (ZSubscr_t *) xmalloc(sizeof(ZSubscr_t)))) { - syslog(LOG_ERR, "no mem subscr_def_subs"); - return(ENOMEM); - } - subs->q_forw = subs->q_back = subs; - subs->zst_dest.classname = subs->zst_dest.inst = - subs->zst_dest.recip = (ZSTRING *) NULL; - who->zct_subs = subs; - } + Destlist *subs; - subs = subscr_copy_def_subs(who->zct_principal->string); - return(add_subscriptions(who, subs, &default_notice)); + subs = subscr_copy_def_subs(who->principal->string); + return add_subscriptions(who, subs, &default_notice); } void subscr_reset() { #if 0 - zdbug((LOG_DEBUG, "subscr_reset()")); + zdbug((LOG_DEBUG, "subscr_reset()")); #endif - xfree(default_notice.z_message); - default_notice.z_message = NULL; - defaults_read = 0; + free(default_notice.z_message); + default_notice.z_message = NULL; + defaults_read = 0; } -static ZSubscr_t * +static Destlist * subscr_copy_def_subs(person) - char *person; + char *person; { - int retval; - int fd; - struct stat statbuf; - char *def_sub_area; - register char *cp; - ZSubscr_t *subs; - register ZSubscr_t *subs2; - - if (!defaults_read) { + int retval, fd; + struct stat statbuf; + char *def_sub_area, *cp; + Destlist *subs, *sub; + + if (!defaults_read) { #if 0 - zdbug((LOG_DEBUG, "reading default subscription file")); + zdbug((LOG_DEBUG, "reading default subscription file")); #endif - fd = open(DEFAULT_SUBS_FILE, O_RDONLY, 0666); - if (fd < 0) { - syslog(LOG_ERR, "can't open %s:%m", DEFAULT_SUBS_FILE); - return((ZSubscr_t *)0); - } - retval = fstat(fd, &statbuf); - if (retval < 0) { - syslog(LOG_ERR, "fstat failure on %s:%m", - DEFAULT_SUBS_FILE); - (void) close(fd); - return((ZSubscr_t *)0); - } - if (!(def_sub_area = (char *) xmalloc(statbuf.st_size + 1))) { - syslog(LOG_ERR, "no mem copy_def_subs"); - (void) close(fd); - return((ZSubscr_t *)0); - } - retval = read(fd, def_sub_area, (int) statbuf.st_size); - /* - "Upon successful completion, read and readv return the number - of bytes actually read and placed in the buffer. The system - guarantees to read the number of bytes requested if the - descriptor references a normal file that has that many bytes - left before the end-of-file, but in no other case." - -- read(2) - Therefore, the following test is valid. - */ - if (retval != statbuf.st_size) { - syslog(LOG_ERR, "short read in copy_def_subs"); - (void) close(fd); - return((ZSubscr_t *)0); - } + fd = open(subs_file, O_RDONLY, 0666); + if (fd < 0) { + syslog(LOG_ERR, "can't open %s:%m", subs_file); + return NULL; + } + retval = fstat(fd, &statbuf); + if (retval < 0) { + syslog(LOG_ERR, "fstat failure on %s:%m", subs_file); + close(fd); + return NULL; + } + def_sub_area = (char *) malloc(statbuf.st_size + 1); + if (!def_sub_area) { + syslog(LOG_ERR, "no mem copy_def_subs"); + close(fd); + return NULL; + } + retval = read(fd, def_sub_area, (size_t) statbuf.st_size); + if (retval != statbuf.st_size) { + syslog(LOG_ERR, "short read in copy_def_subs"); + close(fd); + return NULL; + } + + close(fd); + def_sub_area[statbuf.st_size] = '\0'; /* null-terminate it */ + + /* + def_subs_area now points to a buffer full of subscription info. + Each line of the stuff is of the form: + class,inst,recipient - (void) close(fd); - def_sub_area[statbuf.st_size] = '\0'; /* null-terminate it */ - - /* - def_subs_area now points to a buffer full of subscription - info. - each line of the stuff is of the form: - class,inst,recipient - - Commas and newlines may not appear as part of the class, - instance, or recipient. XXX! - */ - - /* split up the subscription info */ - for (cp = def_sub_area; - cp < def_sub_area + statbuf.st_size; - cp++) - if ((*cp == '\n') || (*cp == ',')) - *cp = '\0'; - default_notice.z_message = def_sub_area; - default_notice.z_message_len = (int) statbuf.st_size + 1; - default_notice.z_auth = 1; - defaults_read = 1; + Commas and newlines may not appear as part of the class, + instance, or recipient. XXX! + */ + + /* split up the subscription info */ + for (cp = def_sub_area; cp < def_sub_area + statbuf.st_size; cp++) { + if (*cp == '\n' || *cp == ',') + *cp = '\0'; } - /* needed later for access_check() */ - default_notice.z_sender = person; - subs = extract_subscriptions(&default_notice); - /* replace any non-* recipients with "person" */ - - for (subs2 = subs->q_forw; subs2 != subs; subs2 = subs2->q_forw) { - /* if not a wildcard, replace it with person */ - if (strcmp(subs2->zst_dest.recip->string, "*")) { - free_zstring(subs2->zst_dest.recip); - subs2->zst_dest.recip = make_zstring(person,0); - } else { /* replace with null recipient */ - free_zstring(subs2->zst_dest.recip); - subs2->zst_dest.recip = dup_zstring(empty); - } + default_notice.z_message = def_sub_area; + default_notice.z_message_len = statbuf.st_size + 1; + default_notice.z_auth = 1; + defaults_read = 1; + } + + /* needed later for access_check() */ + default_notice.z_sender = person; + subs = extract_subscriptions(&default_notice); + /* replace any non-* recipients with "person" */ + + for (sub = subs; sub; sub = sub->next) { + /* if not a wildcard, replace it with person */ + if (strcmp(sub->dest.recip->string, "*")) { + free_string(sub->dest.recip); + sub->dest.recip = make_string(person, 0); + } else { /* replace with null recipient */ + free_string(sub->dest.recip); + sub->dest.recip = dup_string(empty); } - return(subs); + } + return subs; } /* @@ -360,161 +314,163 @@ subscr_copy_def_subs(person) Code_t subscr_cancel(sin, notice) - struct sockaddr_in *sin; - ZNotice_t *notice; + struct sockaddr_in *sin; + ZNotice_t *notice; { - ZClient_t *who; - register ZSubscr_t *cancel_queue, *cancel, *sub; - Code_t retval; - int found = 0; - int relation; + Realm *realm; + Client *who; + Destlist *cancel_subs, *subs, *cancel_next, *client_subs, *client_next; + Code_t retval; + int found = 0; + int relation; #if 0 - zdbug((LOG_DEBUG,"subscr_cancel")); + zdbug((LOG_DEBUG,"subscr_cancel")); #endif - who = client_which_client(sin, notice); - if (!who) - return(ZSRV_NOCLT); - - if (!who->zct_subs) - return(ZSRV_NOSUB); - - cancel_queue = extract_subscriptions(notice); - if (!cancel_queue) - return(ZERR_NONE); /* no subscr -> no error */ - - START_CRITICAL_CODE; - - for (cancel = cancel_queue->q_forw; cancel != cancel_queue; - cancel = cancel->q_forw) { - for (sub = who->zct_subs->q_forw; sub != who->zct_subs; - sub = sub->q_forw) { - if (ZDest_eq(&cancel->zst_dest, &sub->zst_dest)) { - xremque(sub); - triplet_deregister(who, &sub->zst_dest); - free_zstring(sub->zst_dest.classname); - free_zstring(sub->zst_dest.inst); - free_zstring(sub->zst_dest.recip); - xfree(sub); - found = 1; - break; + who = client_which_client(&sin->sin_addr, notice); + if (!who) + return ZSRV_NOCLT; + + if (!who->subs) + return ZSRV_NOSUB; + + cancel_subs = extract_subscriptions(notice); + if (!cancel_subs) + return ZERR_NONE; /* no subscr -> no error */ + + for (subs = cancel_subs; subs; subs = cancel_next) { + cancel_next = subs->next; + for (client_subs = who->subs; client_subs; client_subs = client_next) { + client_next = client_subs->next; + if (ZDest_eq(&client_subs->dest, &subs->dest)) { + LIST_DELETE(client_subs); + triplet_deregister(who, &client_subs->dest, NULL); + if (retval == ZSRV_EMPTYCLASS && + client_subs->dest.recip->string[0] == '@') { + realm = + realm_get_realm_by_name(client_subs->dest.recip->string + + 1); + if (realm) + subscr_unsub_sendit(client_subs, realm); + realm = NULL; } + free_string(client_subs->dest.classname); + free_string(client_subs->dest.inst); + free_string(client_subs->dest.recip); + free(client_subs); + found = 1; + break; } } + } - END_CRITICAL_CODE; + free_subscriptions(cancel_subs); - free_subscriptions(cancel_queue); - if (found) { + if (found) { #if 0 - zdbug((LOG_DEBUG, "found & removed")); + zdbug((LOG_DEBUG, "found & removed")); #endif - return(ZERR_NONE); - } else { + return ZERR_NONE; + } else { #if 0 - zdbug((LOG_DEBUG, "not found")); + zdbug((LOG_DEBUG, "not found")); #endif - return(ZSRV_NOSUB); - } + return ZSRV_NOSUB; + } } -/* - * Cancel all the subscriptions for this client. - */ - -void -subscr_cancel_client(client) - ZClient_t *client; +Code_t +subscr_realm_cancel(sin, notice, realm) + struct sockaddr_in *sin; + ZNotice_t *notice; + Realm *realm; { - register ZSubscr_t *subs; - + Client *who; + Destlist *cancel_subs, *subs, *client_subs, *next, *next2; + Code_t retval; + int found = 0; + + if (!realm) + return ZSRV_NORLM; + + if (!realm->subs) + return ZSRV_NOSUB; + + cancel_subs = extract_subscriptions(notice); + if (!cancel_subs) + return ZERR_NONE; /* no subscr -> no error */ + + for (subs = cancel_subs; subs; subs = next) { + next = subs->next; + for (client_subs = realm->subs; client_subs; client_subs = next2) { + next2 = client_subs->next; + if (ZDest_eq(&client_subs->dest, &subs->dest)) { + LIST_DELETE(client_subs); + retval = triplet_deregister(realm->client, &client_subs->dest, realm); + free_string(client_subs->dest.classname); + free_string(client_subs->dest.inst); + free_string(client_subs->dest.recip); + free(client_subs); + found = 1; + break; + } + } + } + + free_subscriptions(cancel_subs); + + if (found) { #if 0 - zdbug((LOG_DEBUG,"subscr_cancel_client %s", - inet_ntoa (client->zct_addr.sin_addr))); + zdbug((LOG_DEBUG, "found & removed")); #endif - if (!client->zct_subs) - return; - - START_CRITICAL_CODE; - - for (subs = client->zct_subs->q_forw; - subs != client->zct_subs; - subs = client->zct_subs->q_forw) { + return ZERR_NONE; + } else { #if 0 - zdbug((LOG_DEBUG,"sub_can %s", - subs->zst_dest.classname->string)); + zdbug((LOG_DEBUG, "not found")); #endif - if (triplet_deregister(client, &subs->zst_dest) != ZERR_NONE) { -#if 0 - zdbug((LOG_DEBUG,"sub_can_clt: not registered!")); -#endif - } - xremque(subs); - free_zstring(subs->zst_dest.classname); - free_zstring(subs->zst_dest.inst); - free_zstring(subs->zst_dest.recip); - xfree(subs); - } - - /* also flush the head of the queue */ - /* subs is now client->zct_subs */ - free_zstring(subs->zst_dest.classname); - free_zstring(subs->zst_dest.inst); - free_zstring(subs->zst_dest.recip); - xfree(subs); - client->zct_subs = NULLZST; - - END_CRITICAL_CODE; - - return; + return ZSRV_NOSUB; + } } -#ifdef notdef -/* not used for the moment */ /* - * Cancel all the subscriptions for clients at this addr. + * Cancel all the subscriptions for this client. */ -Code_t -subscr_cancel_host(addr) -struct in_addr *addr; +void +subscr_cancel_client(client) + Client *client; { - register ZHostList_t *hosts; - register ZClientList_t *clist = NULLZCLT, *clt; - - /* find the host */ - if (!(hosts = hostm_find_host(addr))) - return(ZSRV_HNOTFOUND); - clist = hosts->zh_clients; - - START_CRITICAL_CODE; - - /* flush each one */ - for (clt = clist->q_forw; clt != clist; clt = clt->q_forw) - (void) subscr_cancel_client(clt->zclt_client); + Destlist *subs, *next; + Code_t retval; + Realm *realm; - END_CRITICAL_CODE; - - return(ZERR_NONE); -} +#if 0 + zdbug((LOG_DEBUG,"subscr_cancel_client %s", + inet_ntoa(client->addr.sin_addr))); #endif + if (!client->subs) + return; -/* - * Free memory used by a list we allocated. - */ - -void -subscr_free_list(list) - ZClientList_t *list; -{ - register ZClientList_t *lyst; - - for (lyst = list->q_forw; lyst != list; lyst = list->q_forw) { - xremque(lyst); - xfree(lyst); + for (subs = client->subs; subs; subs = next) { + next = subs->next; +#if 0 + zdbug((LOG_DEBUG,"sub_can %s", subs->dest.classname->string)); +#endif + retval = triplet_deregister(client, &subs->dest, NULL); + if (retval == ZSRV_EMPTYCLASS && + subs->dest.recip->string[0] == '@') { + realm = realm_get_realm_by_name(subs->dest.recip->string + 1); + if (realm) + subscr_unsub_sendit(subs, realm); + realm = NULL; } - xfree(list); - return; + free_string(subs->dest.classname); + free_string(subs->dest.inst); + free_string(subs->dest.recip); + free(subs); + } + + client->subs = NULL; } /* @@ -523,359 +479,349 @@ subscr_free_list(list) void subscr_sendlist(notice, auth, who) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; { - char **answer; - int found; - struct sockaddr_in send_to_who; - Code_t retval; + char **answer; + int found; + struct sockaddr_in send_to_who; + Code_t retval; #ifdef OLD_COMPAT - if (!strcmp(notice->z_version, OLD_ZEPHYR_VERSION)) { - /* we are talking to an old client; use the old-style - acknowledgement-message */ - old_compat_subscr_sendlist(notice, auth, who); - return; - } + if (strcmp(notice->z_version, OLD_ZEPHYR_VERSION) == 0) { + /* we are talking to an old client; use the old-style + acknowledgement-message */ + old_compat_subscr_sendlist(notice, auth, who); + return; + } #endif /* OLD_COMPAT */ #ifdef NEW_COMPAT - if (!strcmp(notice->z_version, NEW_OLD_ZEPHYR_VERSION)) { - /* we are talking to a new old client; use the new-old-style - acknowledgement-message */ - new_old_compat_subscr_sendlist(notice, auth, who); - return; - } + if (strcmp(notice->z_version, NEW_OLD_ZEPHYR_VERSION) == 0) { + /* we are talking to a new old client; use the new-old-style + acknowledgement-message */ + new_old_compat_subscr_sendlist(notice, auth, who); + return; + } #endif /* NEW_COMPAT */ - answer = subscr_marshal_subs(notice, auth, who, &found); - send_to_who = *who; - send_to_who.sin_port = notice->z_port; /* Return port */ - - if ((retval = ZSetDestAddr(&send_to_who)) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_sendlist set addr: %s", - error_message(retval)); - if (answer) - xfree(answer); - return; - } + answer = subscr_marshal_subs(notice, auth, who, &found); + send_to_who = *who; + send_to_who.sin_port = notice->z_port; /* Return port */ + + retval = ZSetDestAddr(&send_to_who); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_sendlist set addr: %s", + error_message(retval)); + if (answer) + free(answer); + return; + } - /* XXX for now, don't do authentication */ - auth = 0; + /* XXX for now, don't do authentication */ + auth = 0; - notice->z_kind = ACKED; + notice->z_kind = ACKED; - /* use xmit_frag() to send each piece of the notice */ + /* use xmit_frag() to send each piece of the notice */ - if ((retval = ZSrvSendRawList(notice, (char **) answer, - found*NUM_FIELDS, xmit_frag)) - != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_sendlist xmit: %s", - error_message(retval)); - } - if (answer) - xfree(answer); - return; + retval = ZSrvSendRawList(notice, answer, found * NUM_FIELDS, xmit_frag); + if (retval != ZERR_NONE) + syslog(LOG_WARNING, "subscr_sendlist xmit: %s", error_message(retval)); + if (answer) + free(answer); } static char ** subscr_marshal_subs(notice, auth, who, found) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - register int *found; + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + int *found; { - ZNotice_t reply; - char **answer = (char **) 0; - int temp; - Code_t retval; - ZClient_t *client; - register ZSubscr_t *subs, *subs2 = NULLZST; - register int i; - int defsubs = 0; + ZNotice_t reply; + char **answer = NULL; + unsigned short temp; + Code_t retval; + Client *client; + Destlist *subs = NULL, *sub; + int i; + int defsubs = 0; #if 0 - zdbug((LOG_DEBUG, "subscr_marshal")); + zdbug((LOG_DEBUG, "subscr_marshal")); #endif - *found = 0; + *found = 0; - /* Note that the following code is an incredible crock! */ + /* Note that the following code is an incredible crock! */ - /* We cannot send multiple packets as acknowledgements to the client, - since the hostmanager will ignore the later packets. So we need - to send directly to the client. */ + /* We cannot send multiple packets as acknowledgements to the client, + since the hostmanager will ignore the later packets. So we need + to send directly to the client. */ - /* Make our own copy so we can send directly back to the client */ - /* RSF 11/07/87 */ - + /* Make our own copy so we can send directly back to the client */ + /* RSF 11/07/87 */ - if (!strcmp(notice->z_opcode, CLIENT_GIMMESUBS)) { - /* If the client has requested his current subscriptions, - the message field of the notice contains the port number - of the client for which the sender desires the subscription - list. The port field is the port of the sender. */ - - if ((retval = ZReadAscii(notice->z_message, - notice->z_message_len, - (unsigned char *)&temp, - sizeof(u_short))) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_marshal read port num: %s", - error_message(retval)); - return((char **)0); - } + if (strcmp(notice->z_opcode, CLIENT_GIMMESUBS) == 0) { + /* If the client has requested his current subscriptions, + the message field of the notice contains the port number + of the client for which the sender desires the subscription + list. The port field is the port of the sender. */ - /* Blech blech blech */ - reply = *notice; - reply.z_port = *((u_short *)&temp); - - client = client_which_client(who, &reply); - - if (client) - subs2 = client->zct_subs; - } else if (!strcmp(notice->z_opcode, CLIENT_GIMMEDEFS)) { -#if 0 - zdbug((LOG_DEBUG, "gimmedefs")); -#endif - /* subscr_copy_def_subs allocates new pointer rings, so - it must be freed when finished. - the string areas pointed to are static, however.*/ - subs2 = subscr_copy_def_subs(notice->z_sender); - defsubs = 1; - } else { - syslog(LOG_ERR, "subscr_marshal bogus opcode %s", - notice->z_opcode); - return((char **) 0); + retval = ZReadAscii16(notice->z_message, notice->z_message_len, &temp); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_marshal read port num: %s", + error_message(retval)); + return(NULL); } - if (subs2) { + reply = *notice; + reply.z_port = htons(temp); - /* check authenticity here. The user must be authentic to get - a list of subscriptions. If he is not subscribed to - anything, this if-clause fails, and he gets a response - indicating no subscriptions. - if retrieving default subscriptions, don't care about - authentication. */ + client = client_which_client(&who->sin_addr, &reply); - if (!auth && !defsubs) { - return((char **) 0); - } - if (!defsubs) { - if (client && (strcmp(client->zct_principal->string, - notice->z_sender) != 0)) { - zdbug ((LOG_DEBUG, + if (client) + subs = client->subs; + } else if (strcmp(notice->z_opcode, CLIENT_GIMMEDEFS) == 0) { +#if 0 + zdbug((LOG_DEBUG, "gimmedefs")); +#endif + /* subscr_copy_def_subs allocates new pointer rings, so + it must be freed when finished. + the string areas pointed to are static, however.*/ + subs = subscr_copy_def_subs(notice->z_sender); + defsubs = 1; + } else { + syslog(LOG_ERR, "subscr_marshal bogus opcode %s", + notice->z_opcode); + return(NULL); + } + + if (subs) { + + /* check authenticity here. The user must be authentic to get + a list of subscriptions. If he is not subscribed to + anything, this if-clause fails, and he gets a response + indicating no subscriptions. + if retrieving default subscriptions, don't care about + authentication. */ + + if (!auth && !defsubs) + return(NULL); + if (!defsubs) { + if (client && (strcmp(client->principal->string, + notice->z_sender) != 0)) { + zdbug ((LOG_DEBUG, "subscr_marshal: %s requests subs for %s at %s/%d", - notice->z_sender, - client->zct_principal->string, - inet_ntoa (who->sin_addr), - ntohs (who->sin_port))); - return 0; - } - } + notice->z_sender, client->principal->string, + inet_ntoa(who->sin_addr), ntohs(who->sin_port))); + return 0; + } + } + + for (sub = subs; sub; sub = sub->next) + (*found)++; - for (subs = subs2->q_forw; - subs != subs2; - subs = subs->q_forw, (*found)++); - - /* found is now the number of subscriptions */ - - /* coalesce the subscription information into a list of - char *'s */ - if ((answer = (char **) xmalloc((*found) * NUM_FIELDS * sizeof(char *))) == (char **) 0) { - syslog(LOG_ERR, "subscr no mem(answer)"); - *found = 0; - } else - for (i = 0, subs = subs2->q_forw; - i < *found ; - i++, subs = subs->q_forw) { - answer[i*NUM_FIELDS] = subs->zst_dest.classname->string; - answer[i*NUM_FIELDS + 1] = subs->zst_dest.inst->string; - answer[i*NUM_FIELDS + 2] = subs->zst_dest.recip->string; - } + /* found is now the number of subscriptions */ + + /* coalesce the subscription information into a list of char *'s */ + answer = (char **) malloc((*found) * NUM_FIELDS * sizeof(char *)); + if (answer == NULL) { + syslog(LOG_ERR, "subscr no mem(answer)"); + *found = 0; + } else { + i = 0; + for (sub = subs; sub; sub = sub->next) { + answer[i * NUM_FIELDS] = sub->dest.classname->string; + answer[i * NUM_FIELDS + 1] = sub->dest.inst->string; + answer[i * NUM_FIELDS + 2] = sub->dest.recip->string; + i++; + } } - if (defsubs) - free_subscriptions(subs2); - return(answer); + } + if (defsubs) + free_subscriptions(subs); + return answer; } #ifdef NEW_COMPAT static void new_old_compat_subscr_sendlist(notice, auth, who) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; { - Code_t retval; - ZNotice_t reply; - ZPacket_t reppacket; - int packlen, found, count, initfound, zerofound; - char buf[64]; - Zconst char **answer; - struct sockaddr_in send_to_who; - register int i; - - new_compat_count_subscr++; - - syslog(LOG_INFO, "new old subscr, %s", inet_ntoa(who->sin_addr)); - reply = *notice; - reply.z_kind = SERVACK; - reply.z_authent_len = 0; /* save some space */ - reply.z_auth = 0; - - send_to_who = *who; - send_to_who.sin_port = notice->z_port; /* Return port */ - - if ((retval = ZSetDestAddr(&send_to_who)) != ZERR_NONE) { - syslog(LOG_WARNING, "new_old_subscr_sendlist set addr: %s", - error_message(retval)); - return; - } + Code_t retval; + ZNotice_t reply; + ZPacket_t reppacket; + int packlen, found, count, initfound, zerofound; + char buf[64]; + const char **answer; + struct sockaddr_in send_to_who; + int i; + + new_compat_count_subscr++; + + syslog(LOG_INFO, "new old subscr, %s", inet_ntoa(who->sin_addr)); + reply = *notice; + reply.z_kind = SERVACK; + reply.z_authent_len = 0; /* save some space */ + reply.z_auth = 0; + + send_to_who = *who; + send_to_who.sin_port = notice->z_port; /* Return port */ + + retval = ZSetDestAddr(&send_to_who); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "new_old_subscr_sendlist set addr: %s", + error_message(retval)); + return; + } - /* retrieve the subscriptions */ - answer = subscr_marshal_subs(notice, auth, who, &found); + /* retrieve the subscriptions */ + answer = subscr_marshal_subs(notice, auth, who, &found); - /* note that when there are no subscriptions, found == 0, so - we needn't worry about answer being NULL since - ZFormatSmallRawNoticeList won't reference the pointer */ + /* note that when there are no subscriptions, found == 0, so + we needn't worry about answer being NULL since + ZFormatSmallRawNoticeList won't reference the pointer */ - /* send 5 at a time until we are finished */ - count = found?((found-1) / 5 + 1):1; /* total # to be sent */ - i = 0; /* pkt # counter */ + /* send 5 at a time until we are finished */ + count = found?((found-1) / 5 + 1):1; /* total # to be sent */ + i = 0; /* pkt # counter */ #if 0 - zdbug((LOG_DEBUG,"Found %d subscriptions for %d packets", - found,count)); + zdbug((LOG_DEBUG,"Found %d subscriptions for %d packets", found, count)); #endif - initfound = found; - zerofound = (found == 0); - while (found > 0 || zerofound) { - packlen = sizeof(reppacket); - (void) sprintf(buf, "%d/%d", ++i, count); - reply.z_opcode = buf; - retval = ZFormatSmallRawNoticeList(&reply, - answer+(initfound-found)*NUM_FIELDS, - ((found > 5) ? 5 : found)*NUM_FIELDS, - reppacket, - &packlen); - if (retval != ZERR_NONE) { - syslog(LOG_ERR, "subscr_sendlist format: %s", - error_message(retval)); - if (answer) - xfree(answer); - return; - } - if ((retval = ZSendPacket(reppacket, packlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_sendlist xmit: %s", - error_message(retval)); - if (answer) - xfree(answer); - return; - } - found -= 5; - zerofound = 0; + initfound = found; + zerofound = (found == 0); + while (found > 0 || zerofound) { + packlen = sizeof(reppacket); + sprintf(buf, "%d/%d", ++i, count); + reply.z_opcode = buf; + retval = ZFormatSmallRawNoticeList(&reply, + answer + (initfound - found) + * NUM_FIELDS, + ((found > 5) ? 5 : found) + * NUM_FIELDS, + reppacket, &packlen); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "subscr_sendlist format: %s", + error_message(retval)); + if (answer) + free(answer); + return; } + retval = ZSendPacket(reppacket, packlen, 0); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_sendlist xmit: %s", + error_message(retval)); + if (answer) + free(answer); + return; + } + found -= 5; + zerofound = 0; + } #if 0 - zdbug((LOG_DEBUG,"subscr_sendlist acked")); + zdbug((LOG_DEBUG,"subscr_sendlist acked")); #endif - if (answer) - xfree(answer); - return; + if (answer) + free(answer); } #endif /* NEW_COMPAT */ #ifdef OLD_COMPAT static void old_compat_subscr_sendlist(notice, auth, who) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; { - ZClient_t *client = client_which_client(who, notice); - register ZSubscr_t *subs; - Code_t retval; - ZNotice_t reply; - ZPacket_t reppacket; - int packlen, i, found = 0; - char **answer = (char **) NULL; - - old_compat_count_subscr++; - - syslog(LOG_INFO, "old old subscr, %s", inet_ntoa(who->sin_addr)); - if (client && client->zct_subs) { - - /* check authenticity here. The user must be authentic to get - a list of subscriptions. If he is not subscribed to - anything, the above test fails, and he gets a response - indicating no subscriptions */ - - if (!auth) { - clt_ack(notice, who, AUTH_FAILED); - return; - } - - for (subs = client->zct_subs->q_forw; - subs != client->zct_subs; - subs = subs->q_forw, found++); - - /* found is now the number of subscriptions */ - - /* coalesce the subscription information into a list of - char *'s */ - if ((answer = (char **) xmalloc(found * NUM_FIELDS * sizeof(char *))) == (char **) 0) { - syslog(LOG_ERR, "old_subscr_sendlist no mem(answer)"); - found = 0; - } else - for (i = 0, subs = client->zct_subs->q_forw; - i < found ; - i++, subs = subs->q_forw) { - answer[i*NUM_FIELDS] = subs->zst_class; - answer[i*NUM_FIELDS + 1] = subs->zst_classinst; - answer[i*NUM_FIELDS + 2] = subs->zst_recipient; - } + Client *client = client_which_client(&who->sin_addr, notice); + Destlist *subs; + Code_t retval; + ZNotice_t reply; + ZPacket_t reppacket; + int packlen, i, found = 0; + char **answer = NULL; + + old_compat_count_subscr++; + + syslog(LOG_INFO, "old old subscr, %s", inet_ntoa(who->sin_addr)); + if (client && client->subs) { + + /* check authenticity here. The user must be authentic to get + a list of subscriptions. If he is not subscribed to + anything, the above test fails, and he gets a response + indicating no subscriptions */ + + if (!auth) { + clt_ack(notice, who, AUTH_FAILED); + return; } - /* note that when there are no subscriptions, found == 0, so - we needn't worry about answer being NULL */ - reply = *notice; - reply.z_kind = SERVACK; - reply.z_authent_len = 0; /* save some space */ - reply.z_auth = 0; - - - /* if it's too long, chop off one at a time till it fits */ - while ((retval = ZFormatSmallRawNoticeList(&reply, - answer, - found * NUM_FIELDS, - reppacket, - &packlen)) == ZERR_PKTLEN) { - found--; - reply.z_opcode = OLD_CLIENT_INCOMPSUBS; - } - if (retval != ZERR_NONE) { - syslog(LOG_ERR, "old_subscr_sendlist format: %s", - error_message(retval)); - if (answer) - xfree(answer); - return; - } - if ((retval = ZSetDestAddr(who)) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_sendlist set addr: %s", - error_message(retval)); - if (answer) - xfree(answer); - return; - } - if ((retval = ZSendPacket(reppacket, packlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_sendlist xmit: %s", - error_message(retval)); - if (answer) - xfree(answer); - return; + for (subs = client->subs; subs; subs = subs->next) + found++; + /* found is now the number of subscriptions */ + + /* coalesce the subscription information into a list of char *'s */ + answer = (char **) malloc(found * NUM_FIELDS * sizeof(char *)); + if (!answer) { + syslog(LOG_ERR, "old_subscr_sendlist no mem(answer)"); + found = 0; + } else { + i = 0; + for (subs = client->subs; subs; subs = subs->next) { + answer[i*NUM_FIELDS] = subs->dest.classname->string; + answer[i*NUM_FIELDS + 1] = subs->dest.inst->string; + answer[i*NUM_FIELDS + 2] = subs->dest.recip->string; + i++; + } } -#if 0 - zdbug((LOG_DEBUG,"subscr_sendlist acked")); -#endif + } + + /* note that when there are no subscriptions, found == 0, so + we needn't worry about answer being NULL */ + + reply = *notice; + reply.z_kind = SERVACK; + reply.z_authent_len = 0; /* save some space */ + reply.z_auth = 0; + + /* if it's too long, chop off one at a time till it fits */ + while ((retval = ZFormatSmallRawNoticeList(&reply, answer, + found * NUM_FIELDS, + reppacket, + &packlen)) != ZERR_PKTLEN) { + found--; + reply.z_opcode = OLD_CLIENT_INCOMPSUBS; + } + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "old_subscr_sendlist format: %s", + error_message(retval)); if (answer) - xfree(answer); + free(answer); return; + } + retval = ZSetDestAddr(who); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_sendlist set addr: %s", + error_message(retval)); + if (answer) + free(answer); + return; + } + retval = ZSendPacket(reppacket, packlen, 0); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_sendlist xmit: %s", + error_message(retval)); + if (answer) + free(answer); + return; + } +#if 0 + zdbug((LOG_DEBUG,"subscr_sendlist acked")); +#endif + if (answer) + free(answer); } #endif /* OLD_COMPAT */ @@ -888,99 +834,89 @@ old_compat_subscr_sendlist(notice, auth, who) /*ARGSUSED*/ Code_t -subscr_send_subs(client, vers) - ZClient_t *client; - char *vers; +subscr_send_subs(client) + Client *client; { - register int i = 0; - register ZSubscr_t *sub; -#ifdef KERBEROS - char buf[512]; - C_Block cblock; -#endif /* KERBEROS */ - char buf2[512]; - char *lyst[7 * NUM_FIELDS]; - int num = 0; - Code_t retval; + int i = 0; + Destlist *subs; +#ifdef ZEPHYR_USES_KERBEROS + char buf[512]; + C_Block cblock; +#endif /* ZEPHYR_USES_KERBEROS */ + char buf2[512]; + char *list[7 * NUM_FIELDS]; + int num = 0; + Code_t retval; #if 0 - zdbug((LOG_DEBUG, "send_subs")); + zdbug((LOG_DEBUG, "send_subs")); #endif - (void) sprintf(buf2, "%d",ntohs(client->zct_sin.sin_port)); + sprintf(buf2, "%d",ntohs(client->addr.sin_port)); - lyst[num++] = buf2; + list[num++] = buf2; -#ifdef KERBEROS +#ifdef ZEPHYR_USES_KERBEROS #ifdef NOENCRYPTION - (void) memcpy((caddr_t)cblock, (caddr_t)client->zct_cblock, sizeof(C_Block)); + memcpy(cblock, client->session_key, sizeof(C_Block)); #else - des_ecb_encrypt(client->zct_cblock, cblock, serv_ksched.s, DES_ENCRYPT); + des_ecb_encrypt(client->session_key, cblock, serv_ksched.s, DES_ENCRYPT); #endif - if ((retval = ZMakeAscii(buf, sizeof(buf), cblock, - sizeof(C_Block))) != ZERR_NONE) { + retval = ZMakeAscii(buf, sizeof(buf), cblock, sizeof(C_Block)); + if (retval != ZERR_NONE) { #if 0 - zdbug((LOG_DEBUG,"zmakeascii failed: %s", - error_message(retval))); + zdbug((LOG_DEBUG,"zmakeascii failed: %s", error_message(retval))); #endif - } else { - lyst[num++] = buf; + } else { + list[num++] = buf; #if 0 - zdbug((LOG_DEBUG,"cblock %s",buf)); + zdbug((LOG_DEBUG, "cblock %s", buf)); #endif - } -#endif /* KERBEROS */ - if ((retval = bdump_send_list_tcp(SERVACK, client->zct_sin.sin_port, - ZEPHYR_ADMIN_CLASS, - num > 1 ? "CBLOCK" : "", - ADMIN_NEWCLT, - (char*)client->zct_principal->string, - "", lyst, num)) != ZERR_NONE ) { - syslog(LOG_ERR, "subscr_send_subs newclt: %s", + } +#endif /* ZEPHYR_USES_KERBEROS */ + retval = bdump_send_list_tcp(SERVACK, &client->addr, ZEPHYR_ADMIN_CLASS, + num > 1 ? "CBLOCK" : "", ADMIN_NEWCLT, + client->principal->string, "", list, num); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "subscr_send_subs newclt: %s", error_message(retval)); + return retval; + } + + if (!client->subs) + return ZERR_NONE; + + for (subs = client->subs; subs; subs = subs->next) { + /* for each subscription */ + list[i * NUM_FIELDS] = subs->dest.classname->string; + list[i * NUM_FIELDS + 1] = subs->dest.inst->string; + list[i * NUM_FIELDS + 2] = subs->dest.recip->string; + i++; + if (i >= 7) { + /* we only put 7 in each packet, so we don't run out of room */ + retval = bdump_send_list_tcp(ACKED, &client->addr, + ZEPHYR_CTL_CLASS, "", + CLIENT_SUBSCRIBE, "", "", list, + i * NUM_FIELDS); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "subscr_send_subs subs: %s", error_message(retval)); - return(retval); - } - - if (!client->zct_subs) - return(ZERR_NONE); - for (sub = client->zct_subs->q_forw; - sub != client->zct_subs; - sub = sub->q_forw) { - /* for each subscription */ - lyst[i * NUM_FIELDS] = sub->zst_dest.classname->string; - lyst[i * NUM_FIELDS + 1] = sub->zst_dest.inst->string; - lyst[i * NUM_FIELDS + 2] = sub->zst_dest.recip->string; - i++; - if (i >= 7) { - /* we only put 7 in each packet, so we don't - run out of room */ - if ((retval = bdump_send_list_tcp(ACKED, - client->zct_sin.sin_port, - ZEPHYR_CTL_CLASS, "", - CLIENT_SUBSCRIBE, "", - "", lyst, - i * NUM_FIELDS)) - != ZERR_NONE) { - syslog(LOG_ERR, "subscr_send_subs subs: %s", - error_message(retval)); - return(retval); - } - i = 0; - } + return retval; + } + i = 0; } - if (i) { - if ((retval = bdump_send_list_tcp(ACKED, - client->zct_sin.sin_port, - ZEPHYR_CTL_CLASS, "", - CLIENT_SUBSCRIBE, "", "", - lyst, i * NUM_FIELDS)) - != ZERR_NONE) { - syslog(LOG_ERR, "subscr_send_subs subs: %s", - error_message(retval)); - return(retval); - } + } + if (i) { + retval = bdump_send_list_tcp(ACKED, &client->addr, ZEPHYR_CTL_CLASS, + "", CLIENT_SUBSCRIBE, "", "", list, + i * NUM_FIELDS); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "subscr_send_subs subs: %s", + error_message(retval)); + return retval; } - return(ZERR_NONE); + } + + return ZERR_NONE; } /* @@ -989,85 +925,72 @@ subscr_send_subs(client, vers) static void free_subscriptions(subs) - register ZSubscr_t *subs; + Destlist *subs; { - register ZSubscr_t *sub; - - for (sub = subs->q_forw; sub != subs; sub = subs->q_forw) { - xremque(sub); - free_zstring(sub->zst_dest.classname); - free_zstring(sub->zst_dest.inst); - free_zstring(sub->zst_dest.recip); - xfree(sub); - } - free_zstring(subs->zst_dest.classname); - free_zstring(subs->zst_dest.inst); - free_zstring(subs->zst_dest.recip); - xfree(subs); - - return; + Destlist *next; + + for (; subs; subs = next) { + next = subs->next; + free_string(subs->dest.classname); + free_string(subs->dest.inst); + free_string(subs->dest.recip); + free(subs); + } } #define ADVANCE(xx) { cp += (strlen(cp) + 1); \ if (cp >= notice->z_message + notice->z_message_len) { \ - syslog(LOG_WARNING, "malformed subscription %d", xx); \ - return(subs); \ + syslog(LOG_WARNING, "malformed subscription %d", \ + xx); \ + return subs; \ }} /* * Parse the message body, returning a linked list of subscriptions, or - * NULLZST if there are no subscriptions there. + * NULL if there are no subscriptions there. */ -static ZSubscr_t * +static Destlist * extract_subscriptions(notice) - register ZNotice_t *notice; + ZNotice_t *notice; { - register ZSubscr_t *subs = NULLZST, *subs2; - register char *recip, *class_name, *classinst; - register char *cp = notice->z_message; - - /* parse the data area for the subscriptions */ - while (cp < notice->z_message + notice->z_message_len) { - class_name = cp; - if (*cp == '\0') - /* we've exhausted the subscriptions */ - return(subs); - ADVANCE(1); - classinst = cp; - ADVANCE(2); - recip = cp; + Destlist *subs = NULL, *sub; + char *recip, *class_name, *classinst; + char *cp = notice->z_message; + + /* parse the data area for the subscriptions */ + while (cp < notice->z_message + notice->z_message_len) { + class_name = cp; + if (*cp == '\0') /* we've exhausted the subscriptions */ + return(subs); + ADVANCE(1); + classinst = cp; + ADVANCE(2); + recip = cp; #if 0 - zdbug((LOG_DEBUG, "ext_sub: CLS %s INST %s RCPT %s", - class_name, classinst, cp)); + zdbug((LOG_DEBUG, "ext_sub: CLS %s INST %s RCPT %s", + class_name, classinst, cp)); #endif - cp += (strlen(cp) + 1); - if (cp > notice->z_message + notice->z_message_len) { - syslog(LOG_WARNING, "malformed sub 3"); - return(subs); - } - if (!subs) { - if (!(subs = (ZSubscr_t *) - xmalloc(sizeof(ZSubscr_t)))) { - syslog(LOG_WARNING, "ex_subs: no mem"); - return(NULLZST); - } - subs->q_forw = subs->q_back = subs; - subs->zst_dest.classname = subs->zst_dest.inst = - subs->zst_dest.recip = NULL; - } - if (!(subs2 = (ZSubscr_t *) xmalloc(sizeof(ZSubscr_t)))) { - syslog(LOG_WARNING, "ex_subs: no mem 2"); - return(subs); - } - subs2->q_forw = subs2->q_back = subs2; - subs2->zst_dest.classname = make_zstring(class_name,1); - subs2->zst_dest.inst = make_zstring(classinst,1); - subs2->zst_dest.recip = make_zstring(recip,0); - - xinsque(subs2, subs); + cp += (strlen(cp) + 1); + if (cp > notice->z_message + notice->z_message_len) { + syslog(LOG_WARNING, "malformed sub 3"); + return subs; + } + sub = (Destlist *) malloc(sizeof(Destlist)); + if (!sub) { + syslog(LOG_WARNING, "ex_subs: no mem 2"); + return subs; } - return(subs); + sub->dest.classname = make_string(class_name, 1); + sub->dest.inst = make_string(classinst, 1); + /* Nuke @REALM if REALM is us. */ + if (recip[0] == '@' && !strcmp(recip + 1, ZGetRealm())) + sub->dest.recip = make_string("", 0); + else + sub->dest.recip = make_string(recip, 0); + LIST_INSERT(&subs, sub); + } + return subs; } /* @@ -1078,24 +1001,538 @@ extract_subscriptions(notice) void subscr_dump_subs(fp, subs) - FILE *fp; - ZSubscr_t *subs; + FILE *fp; + Destlist *subs; { - register ZSubscr_t *ptr; - register char *p; + char *p; - if (!subs) /* no subscriptions to dump */ - return; - - for (ptr = subs->q_forw; ptr != subs; ptr = ptr->q_forw) { - fputs("\t\t'", fp); - subscr_quote(ptr->zst_dest.classname->string, fp); - fputs("' '", fp); - subscr_quote(ptr->zst_dest.inst->string, fp); - fputs("' '", fp); - subscr_quote(ptr->zst_dest.recip->string, fp); - fputs("'\n", fp); - } + if (!subs) /* no subscriptions to dump */ return; + + for (; subs; subs = subs->next) { + fputs("\t\t'", fp); + dump_quote(subs->dest.classname->string, fp); + fputs("' '", fp); + dump_quote(subs->dest.inst->string, fp); + fputs("' '", fp); + dump_quote(subs->dest.recip->string, fp); + fputs("'\n", fp); + } +} + +#define I_ADVANCE(xx) { cp += (strlen(cp) + 1); \ + if (cp >= notice->z_message + notice->z_message_len) { \ + syslog(LOG_WARNING, "malformed subscription %d", \ + xx); \ + return (ZERR_NONE); \ + }} + +/* As it exists, this function expects to take only the first sub from the + * Destlist. At some point, it and the calling code should be replaced */ +static Code_t +subscr_realm_sendit(who, subs, notice, realm) + Client *who; + Destlist *subs; + ZNotice_t *notice; + Realm *realm; +{ +#if 0 + Destlist *subs2; +#endif + ZNotice_t snotice; + char *pack; + int packlen; + int found = 0, i; + char **text; + Code_t retval; + char addr[16]; /* xxx.xxx.xxx.xxx max */ + char port[16]; + +#if 0 + zdbug((LOG_DEBUG, "subscr_rlm_sendit")); +#endif + + +#ifdef notdef + for (subs2 = subs; subs2; subs2 = subs2->next, found++); + /* found is now the number of subscriptions */ + + /* coalesce the subscription information into a list of char *'s */ + /* one extra for client information */ + if ((text = (char **) malloc((found * NUM_FIELDS + 2) + * sizeof(char *))) == (char **) 0) + { + syslog(LOG_ERR, "subscr_rlm_sendit malloc"); + return(ENOMEM); + } +#endif /* notdef */ + + if ((text=(char **)malloc((NUM_FIELDS + 2)*sizeof(char *))) == (char **)0) { + syslog(LOG_ERR, "subscr_rlm_sendit malloc"); + return(ENOMEM); + } + /* convert the address to a string of the form x.x.x.x/port */ + strcpy(addr, inet_ntoa(notice->z_sender_addr)); + if ((retval = ZMakeAscii(port, sizeof(port), (unsigned char *) + ¬ice->z_port, sizeof(u_short))) != ZERR_NONE) + { + syslog(LOG_ERR, "subscr_rlm_sendit make ascii: %s", + error_message(retval)); + return(ZERR_NONE); + } + text[0] = addr; + text[1] = port; + +#ifdef notdef + for (i = 0, subs2 = subs; subs2, i < found ; i++, subs2 = subs2->next) { + text[i*NUM_FIELDS + 2] = subs2->dest.classname->string; + text[i*NUM_FIELDS + 3] = subs2->dest.inst->string; + text[i*NUM_FIELDS + 4] = subs2->dest.recip->string; + } +#endif /* notdef */ + + text[2] = subs->dest.classname->string; + text[3] = subs->dest.inst->string; + text[4] = subs->dest.recip->string; + + /* format snotice */ + snotice.z_class_inst = ZEPHYR_CTL_REALM; + snotice.z_opcode = REALM_REQ_SUBSCRIBE; + snotice.z_port = srv_addr.sin_port; + + snotice.z_class = ZEPHYR_CTL_CLASS; + + snotice.z_recipient = ""; + snotice.z_kind = ACKED; + snotice.z_num_other_fields = 0; + snotice.z_default_format = ""; + snotice.z_sender = notice->z_sender; + snotice.z_recipient = notice->z_recipient; + snotice.z_default_format = notice->z_default_format; + +#ifdef notdef + if ((retval = ZFormatNoticeList(&snotice, text, found * NUM_FIELDS + 2, + &pack, &packlen, ZNOAUTH)) != ZERR_NONE) +#else + if ((retval = ZFormatNoticeList(&snotice, text, NUM_FIELDS + 2, + &pack, &packlen, ZNOAUTH)) != ZERR_NONE) +#endif + { + syslog(LOG_WARNING, "subscr_rlm_sendit format: %s", + error_message(retval)); + free(text); + return(ZERR_NONE); + } + free(text); + + if ((retval = ZParseNotice(pack, packlen, &snotice)) != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_rlm_sendit parse: %s", + error_message(retval)); + free(pack); + return(ZERR_NONE); + } + +#if 0 + zdbug((LOG_DEBUG,"subscr_rlm_sendit len: %d", snotice.z_message_len)); +#endif + realm_handoff(&snotice, 1, &(who->addr), realm, 0); + free(pack); + + return(ZERR_NONE); +} + +static Code_t +subscr_add_raw(client, realm, newsubs) + Client *client; + Realm *realm; + Destlist *newsubs; +{ + Destlist *subs, *subs2, *subs3, **head; + Code_t retval; + +#if 0 + zdbug((LOG_DEBUG, "subscr_add_raw")); +#endif + head = (realm) ? &realm->subs : &client->subs; + + /* Loop over the new subscriptions. */ + for (subs = newsubs; subs; subs = subs2) { + subs2 = subs->next; +#ifdef DEBUG + zdbug((LOG_DEBUG,"subscr_add_raw: %s/%s/%s", subs->dest.classname->string, subs->dest.inst->string, subs->dest.recip->string)); + if (realm) + zdbug((LOG_DEBUG,"subscr_add_raw: realm is %s", realm->name)); +#endif + retval = triplet_register(client, &subs->dest, realm); + if (retval != ZERR_NONE) { + free(subs); + if (retval == ZSRV_CLASSXISTS) { + continue; + } else { + free_subscriptions(subs2); + return retval; + } + } + LIST_INSERT(head, subs); + } + return ZERR_NONE; +} + +Code_t +subscr_realm(realm, notice) + Realm *realm; + ZNotice_t *notice; +{ + Destlist *newsubs; + + newsubs = extract_subscriptions(notice); + + if (!newsubs) { + syslog(LOG_WARNING, "empty subs in subscr_realm"); + return(ZERR_NONE); + } + + return(subscr_add_raw(realm->client, realm, newsubs)); +} + +/* Like realm_sendit, this only takes one item from subs */ +static void +subscr_unsub_sendit(subs, realm) + Destlist *subs; + Realm *realm; +{ + ZNotice_t unotice; + Code_t retval; +#ifdef notdef + char *list[7 * NUM_FIELDS]; +#else /* notdef */ + char *list[NUM_FIELDS]; +#endif /* notdef */ + char *pack; + int packlen; + int found = 0; + Destlist *subs2; + + unotice.z_class = ZEPHYR_CTL_CLASS; + unotice.z_class_inst = ZEPHYR_CTL_REALM; + unotice.z_opcode = REALM_UNSUBSCRIBE; + unotice.z_recipient = ""; + unotice.z_kind = ACKED; + + unotice.z_sender = ""; + unotice.z_port = srv_addr.sin_port; + unotice.z_num_other_fields = 0; + unotice.z_default_format = ""; + +#ifdef notdef + found = 0; + for (subs2 = subs; subs2; subs2 = subs2->next) { + list[found * NUM_FIELDS] = subs2->dest.classname->string; + list[found * NUM_FIELDS + 1] = subs2->dest.inst->string; + list[found * NUM_FIELDS + 2] = ""; + + found++; + + if (found >= 7) { + if ((retval = ZFormatNoticeList(&unotice, list, found * NUM_FIELDS, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_unsub_sendit format: %s", + error_message(retval)); + return; + } + if ((retval = ZParseNotice(pack, packlen, &unotice)) != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_unsub_sendit parse: %s", + error_message(retval)); + free(pack); + return; + } + free(pack); + realm_handoff(&unotice, 1, (struct sockaddr_in *) 0, realm, 0); + found = 0; + } + } + + if (found == 0) + return; + + if ((retval = ZFormatNoticeList(&unotice, list, found * NUM_FIELDS, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_unsub_sendit format: %s", + error_message(retval)); + return; + } +#else /* notdef */ + list[0] = subs->dest.classname->string; + list[1] = subs->dest.inst->string; + list[2] = ""; + + if ((retval = ZFormatNoticeList(&unotice, list, NUM_FIELDS, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_unsub_sendit format: %s", + error_message(retval)); + return; + } +#endif /* notdef */ + + if ((retval = ZParseNotice(pack, packlen, &unotice)) != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_unsub_sendit parse: %s", + error_message(retval)); + free(pack); + return; + } + free(pack); + realm_handoff(&unotice, 1, (struct sockaddr_in *) 0, realm, 0); +} + +Code_t +subscr_send_realm_subs(realm) + Realm *realm; +{ + int i = 0; + Destlist *subs, *next; + char buf[512]; + char *list[7 * NUM_FIELDS]; + int num = 0; + Code_t retval; + +#if 0 + zdbug((LOG_DEBUG, "send_realm_subs")); +#endif + + strcpy(buf, realm->name); + list[num++] = buf; + + retval = bdump_send_list_tcp(SERVACK, &srv_addr, ZEPHYR_ADMIN_CLASS, + "", ADMIN_NEWREALM, "", "", list, num); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "subscr_send_realm_subs newclt: %s", error_message(retval)); + return retval; + } + + if (!realm->subs) + return ZERR_NONE; + + for (subs=realm->subs; subs; subs = next) { + next = subs->next; +#ifdef DEBUG + zdbug ((LOG_DEBUG, "send_realm_subs: %s/%s/%s", subs->dest.classname->string, + subs->dest.inst->string, subs->dest.recip->string)); +#endif + /* for each subscription */ + list[i * NUM_FIELDS] = subs->dest.classname->string; + list[i * NUM_FIELDS + 1] = subs->dest.inst->string; + list[i * NUM_FIELDS + 2] = subs->dest.recip->string; + i++; + if (i >= 7) { + /* we only put 7 in each packet, so we don't run out of room */ + retval = bdump_send_list_tcp(ACKED, &srv_addr, + ZEPHYR_CTL_CLASS, "", + REALM_SUBSCRIBE, "", "", list, + i * NUM_FIELDS); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "subscr_send_realm_subs subs: %s", + error_message(retval)); + return retval; + } + i = 0; + } + } + if (i) { + retval = bdump_send_list_tcp(ACKED, &srv_addr, ZEPHYR_CTL_CLASS, + "", REALM_SUBSCRIBE, "", "", list, + i * NUM_FIELDS); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "subscr_send_realm_subs subs: %s", + error_message(retval)); + return retval; + } + } + + return ZERR_NONE; +} + +static Code_t +subscr_check_foreign_subs(notice, who, realm, newsubs) + ZNotice_t *notice; + struct sockaddr_in *who; + Realm *realm; + Destlist *newsubs; +{ + Destlist *subs, *subs2, *next; + Acl *acl; + char **text; + int found = 0; + ZNotice_t snotice; + char *pack, *cp; + int packlen; + Code_t retval; + String *sender; + + for (subs = newsubs; subs; subs = subs->next) + found++; + + if (found == 0) + return(ZERR_NONE); + + sender = make_string(notice->z_sender, 0); + + if ((text = (char **)malloc((found * NUM_FIELDS + 2) * sizeof(char *))) == (char **) 0) { + syslog(LOG_ERR, "subscr_ck_forn_subs no mem(text)"); + return(ENOMEM); + } + + /* grab the client information from the incoming message */ + cp = notice->z_message; + text[0] = cp; + + I_ADVANCE(2); + text[1] = cp; + + I_ADVANCE(3); + + found = 0; + for (subs = newsubs; subs; subs = next) { + next=subs->next; + acl = class_get_acl(subs->dest.classname); + if (acl) { + if (!access_check(sender->string, acl, SUBSCRIBE)) { + syslog(LOG_WARNING, "subscr unauth %s class %s", + sender->string, subs->dest.classname->string); + continue; /* the for loop */ + } + if (wildcard_instance == subs->dest.inst) { + if (!access_check(sender->string, acl, INSTWILD)) { + syslog(LOG_WARNING, + "subscr unauth %s class %s wild inst", + sender->string, subs->dest.classname->string); + continue; + } + } + } + + /* okay to subscribe. save for return trip */ + text[found*NUM_FIELDS + 2] = subs->dest.classname->string; + text[found*NUM_FIELDS + 3] = subs->dest.inst->string; + text[found*NUM_FIELDS + 4] = ""; + found++; + + retval = triplet_register(realm->client, &subs->dest, realm); +#ifdef DEBUG + zdbug ((LOG_DEBUG, "ck_frn_subs: %s/%s/%s", subs->dest.classname->string, + subs->dest.inst->string, subs->dest.recip->string)); +#endif + + if (retval != ZERR_NONE) { + if (retval == ZSRV_CLASSXISTS) { + continue; + } else { + free_subscriptions(subs->next); + free(text); + return retval; + } + } + LIST_INSERT(&realm->subs, subs); + } + /* don't send confirmation if we're not the initial server contacted */ + if (!(server_which_server(who) || found == 0)) { + snotice = *notice; + snotice.z_opcode = REALM_ADD_SUBSCRIBE; + snotice.z_class_inst = ZEPHYR_CTL_REALM; + snotice.z_port = srv_addr.sin_port; + if ((retval = ZFormatNoticeList(&snotice, text, found * NUM_FIELDS + 2, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_ck_forn_subs format: %s", + error_message(retval)); + free(text); + return(ZERR_NONE); + } + if ((retval = ZParseNotice(pack, packlen, &snotice)) != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_ck_forn_subs parse: %s", + error_message(retval)); + free(text); + free(pack); + return(ZERR_NONE); + } + realm_handoff(&snotice, 1, who, realm, 0); + free(pack); + } + free(text); + return ZERR_NONE; +} + +Code_t subscr_foreign_user(notice, who, realm) + ZNotice_t *notice; + struct sockaddr_in *who; + Realm *realm; +{ + Destlist *newsubs, *temp; + Acl *acl; + Code_t status; + Client *client; + ZNotice_t snotice; + struct sockaddr_in newwho; + char *cp; + char rlm_recipient[REALM_SZ + 1]; + +#if 0 + zdbug((LOG_DEBUG, "subscr_foreign_user")); +#endif + + cp = notice->z_message; + + newwho.sin_addr.s_addr = inet_addr(cp); + if (newwho.sin_addr.s_addr == -1) { + syslog(LOG_ERR, "malformed addr from %s, notice->z_sender"); + return(ZERR_NONE); + } + + I_ADVANCE(0); + + snotice = *notice; + + if ((status = ZReadAscii(cp, strlen(cp), (unsigned char *)&snotice.z_port, sizeof(u_short))) + != ZERR_NONE) + { + syslog(LOG_ERR, "subscr_foreign_user read ascii: %s", + error_message(status)); + return(ZERR_NONE); + } + + I_ADVANCE(1); + + snotice.z_message = cp; + snotice.z_message_len = notice->z_message_len - (cp - notice->z_message); + + newsubs = extract_subscriptions(&snotice); + if (!newsubs) { + syslog(LOG_WARNING, "empty subscr for %s", notice->z_sender); + return(ZERR_NONE); + } + + if (!strcmp(snotice.z_opcode, REALM_ADD_SUBSCRIBE)) { + /* this was approved by the other realm, add subscriptions */ + + client = client_which_client(&newwho.sin_addr, &snotice); + if (client == (Client *)0) { + syslog(LOG_WARNING, "no client at %s/%d", + inet_ntoa(newwho.sin_addr), ntohs(snotice.z_port)); + free_subscriptions(newsubs); + return(ZERR_NONE); + } + + /* translate the recipient to represent the foreign realm */ + sprintf(rlm_recipient, "@%s", realm->name); + for (temp = newsubs; temp; temp = temp->next) { +#if 0 + syslog(LOG_DEBUG, "in foreign_user: class is %s", temp->dest.classname->string); +#endif + temp->dest.recip = make_string(rlm_recipient, 0); + } + + status = subscr_add_raw(client, (Realm *)0, newsubs); + } else if (!strcmp(snotice.z_opcode, REALM_REQ_SUBSCRIBE)) { + status = subscr_check_foreign_subs(notice, who, realm, newsubs); + } else { + syslog(LOG_ERR, "bogus opcode %s in subscr_forn_user", + snotice.z_opcode); + status = ZERR_NONE; + } + return(status); } diff --git a/server/subscr.c.old b/server/subscr.c.old deleted file mode 100644 index cb2b110..0000000 --- a/server/subscr.c.old +++ /dev/null @@ -1,1384 +0,0 @@ -/* This file is part of the Project Athena Zephyr Notification System. - * It contains functions for managing subscription lists. - * - * Created by: John T. Kohl - * - * $Source$ - * $Author$ - * - * Copyright (c) 1987,1988 by the Massachusetts Institute of Technology. - * For copying and distribution information, see the file - * "mit-copyright.h". - */ - -#include <zephyr/mit-copyright.h> - -#ifndef lint -#ifndef SABER -static char rcsid_subscr_c[] = "$Id$"; -#endif -#endif - -/* - * The subscription manager. - * - * External functions: - * - * Code_t subscr_subscribe(who, notice) - * ZClient_t *who; - * ZNotice_t *notice; - * - * Code_t subscr_cancel(sin, notice) - * struct sockaddr_in *sin; - * ZNotice_t *notice; - * - * Code_t subscr_cancel_client(client) - * ZClient_t *client; - * - * Code_t subscr_cancel_host(addr) - * struct in_addr *addr; - * - * ZClientList_t *subscr_match_list(notice) - * ZNotice_t *notice; - * - * void subscr_free_list(list) - * ZClientList_t *list; - * - * void subscr_sendlist(notice, auth, who) - * ZNotice_t *notice; - * int auth; - * struct sockaddr_in *who; - * - * Code_t subscr_send_subs(client, vers) - * ZClient_t *client; - * char *vers; - * - * Code_t subscr_def_subs(who) - * ZClient_t *who; - * - * void subscr_reset(); - * - */ - -#include "zserver.h" -#include <ctype.h> -#include <strings.h> -#include <sys/stat.h> - -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -#ifdef KERBEROS -#ifndef NOENCRYPTION -C_Block serv_key; -Sched serv_ksched; -#endif -#endif - -/* for compatibility when sending subscription information to old clients */ - -static void check_sub_order P((ZSubscr_t *subs, int wc)); -#ifdef OLD_COMPAT -#define OLD_ZEPHYR_VERSION "ZEPH0.0" -#define OLD_CLIENT_INCOMPSUBS "INCOMP" -static void old_compat_subscr_sendlist P((ZNotice_t *notice, int auth, - struct sockaddr_in *who)); -extern int old_compat_count_subscr; /* counter of old use */ -#endif /* OLD_COMPAT */ -#ifdef NEW_COMPAT -#define NEW_OLD_ZEPHYR_VERSION "ZEPH0.1" -static void new_old_compat_subscr_sendlist P((ZNotice_t *notice, int auth, - struct sockaddr_in *who)); -extern int new_compat_count_subscr; /* counter of old use */ -#endif /* NEW_COMPAT */ - -extern char *re_comp(), *re_conv(); -static ZSubscr_t *extract_subscriptions P((register ZNotice_t *notice)); -static int clt_unique P((ZClient_t *clt, ZClientList_t *clist)); -static void free_subscriptions P((register ZSubscr_t *subs)); -static char **subscr_marshal_subs P((ZNotice_t *notice, int auth, - struct sockaddr_in *who, - register int *found)); -static Code_t subscr_subscribe_real P((ZClient_t *who, ZSubscr_t *newsubs, - ZNotice_t *notice)); -static ZSubscr_t *subscr_copy_def_subs P((char *)); -static int cl_match P((ZSubscr_t*, ZClient_t *)); - -static int defaults_read = 0; /* set to 1 if the default subs - are in memory */ -static ZNotice_t default_notice; /* contains default subscriptions */ - -#undef P - -ZSTRING *wildcard_class; -ZSTRING *wildcard_instance; -ZSTRING *empty; -ZSubscr_t matchall_sub; - -/* WARNING: make sure this is the same as the number of strings you */ -/* plan to hand back to the user in response to a subscription check, */ -/* else you will lose. See subscr_sendlist() */ -#define NUM_FIELDS 3 - -/* - * subscribe the client to types described in notice. - */ - -Code_t -subscr_subscribe(who, notice) - ZClient_t *who; - ZNotice_t *notice; -{ - ZSubscr_t *subs; - - if (!who->zct_subs) { - /* allocate a subscription head */ - if (!(subs = (ZSubscr_t *) xmalloc(sizeof(ZSubscr_t)))) - return(ENOMEM); - subs->q_forw = subs->q_back = subs; - subs->zst_dest.classname = subs->zst_dest.inst = - subs->zst_dest.recip = NULL; - subs->zst_dest.hash_value = 0; - who->zct_subs = subs; - } - - if (!(subs = extract_subscriptions(notice))) - return(ZERR_NONE); /* no subscr -> no error */ - - return(subscr_subscribe_real(who, subs, notice)); -} - -static Code_t -subscr_subscribe_real(who, newsubs, notice) - ZClient_t *who; - register ZSubscr_t *newsubs; - ZNotice_t *notice; -{ - Code_t retval; - ZAcl_t *acl; - ZSTRING *sender; - ZSubscr_t *subs2, *subs3, *subs; - int relation; - - sender = make_zstring(notice->z_sender,0); - - START_CRITICAL_CODE; - - for (subs = newsubs->q_forw; - subs != newsubs; - subs = subs->q_forw) { - /* for each new subscription */ - -#if 0 - zdbug ((LOG_DEBUG, "subscr: %s/%s/%s", - subs->zst_dest.classname->string, - subs->zst_dest.inst->string, - subs->zst_dest.recip->string)); -#endif - - if (!bdumping - && (subs->zst_dest.recip != empty) - && (subs->zst_dest.recip != sender)) { - syslog(LOG_WARNING, "subscr unauth %s recipient %s", - sender->string, - subs->zst_dest.recip->string); - continue; - } - if (!bdumping) { - acl = class_get_acl(subs->zst_dest.classname); - if (acl) { - if (!(access_check(sender->string, acl, SUBSCRIBE))) { - syslog(LOG_WARNING, - "subscr unauth %s class %s", - sender->string, - subs->zst_dest.classname->string); - continue; /* the for loop */ - } - if (wildcard_instance == subs->zst_dest.inst) { - if (!access_check(sender->string, acl, INSTWILD)) { - syslog(LOG_WARNING, - "subscr unauth %s class %s wild inst", - notice->z_sender, - subs->zst_dest.classname->string); - continue; - } - } - } - } - /* subscriptions are stored in ascending order by */ - /* subscription hash value */ - /* Scan through list to check for duplicates, and to find */ - /* where to insert these subs */ - - for (subs2 = who->zct_subs->q_forw; - subs2 != who->zct_subs; - subs2 = subs2->q_forw) { - /* for each existing subscription */ - relation = compare_subs(subs2,subs,0); - if (relation == 0) - goto duplicate; - if (relation > 0) /* we have passed last possible one */ - break; - if (relation < 0) /* nope... */ - continue; - } - - /* subs2 now points to the first class which is greater - than the new class. We need to back up so that the - insertion below goes BEFORE this one (i.e. after the - previous one) */ - subs2 = subs2->q_back; - - /* ok, we are a new subscription. register and chain on. */ - - if (!(subs3 = (ZSubscr_t *) xmalloc(sizeof(ZSubscr_t)))) { - free_subscriptions(newsubs); - END_CRITICAL_CODE; - return(ENOMEM); - } - - subs3->q_forw = subs3->q_back = subs3; - subs3->zst_dest.classname = - dup_zstring(subs->zst_dest.classname); - subs3->zst_dest.inst = dup_zstring(subs->zst_dest.inst); - subs3->zst_dest.recip = dup_zstring(subs->zst_dest.recip); - set_ZDestination_hash(&subs3->zst_dest); - - if ((retval = class_register(who, subs)) != ZERR_NONE) { - xfree(subs3); - free_subscriptions(newsubs); - END_CRITICAL_CODE; - return(retval); - } - - /* subs2 was adjusted above */ - xinsque(subs3, subs2); - duplicate: - ; - } - - END_CRITICAL_CODE; - - free_subscriptions(newsubs); - return(ZERR_NONE); -} - -/* - * add default subscriptions to the client's subscription chain. - */ - -Code_t -subscr_def_subs(who) - ZClient_t *who; -{ - ZSubscr_t *subs; - - if (!who->zct_subs) { - /* allocate a subscription head */ - if (!(subs = (ZSubscr_t *) xmalloc(sizeof(ZSubscr_t)))) { - syslog(LOG_ERR, "no mem subscr_def_subs"); - return(ENOMEM); - } - subs->q_forw = subs->q_back = subs; - subs->zst_dest.classname = subs->zst_dest.inst = - subs->zst_dest.recip = (ZSTRING *) NULL; - subs->zst_dest.hash_value = 0; - who->zct_subs = subs; - } - - subs = subscr_copy_def_subs(who->zct_principal->string); - return(subscr_subscribe_real(who, subs, &default_notice)); -} - -void -subscr_reset() -{ -#if 0 - zdbug((LOG_DEBUG, "subscr_reset()")); -#endif - xfree(default_notice.z_message); - default_notice.z_message = NULL; - defaults_read = 0; -} - -static ZSubscr_t * -subscr_copy_def_subs(person) - char *person; -{ - int retval; - int fd; - struct stat statbuf; - char *def_sub_area; - register char *cp; - ZSubscr_t *subs; - register ZSubscr_t *subs2; - - if (!defaults_read) { -#if 0 - zdbug((LOG_DEBUG, "reading default subscription file")); -#endif - fd = open(DEFAULT_SUBS_FILE, O_RDONLY, 0666); - if (fd < 0) { - syslog(LOG_ERR, "can't open %s:%m", DEFAULT_SUBS_FILE); - return((ZSubscr_t *)0); - } - retval = fstat(fd, &statbuf); - if (retval < 0) { - syslog(LOG_ERR, "fstat failure on %s:%m", - DEFAULT_SUBS_FILE); - (void) close(fd); - return((ZSubscr_t *)0); - } - if (!(def_sub_area = (char *) xmalloc(statbuf.st_size + 1))) { - syslog(LOG_ERR, "no mem copy_def_subs"); - (void) close(fd); - return((ZSubscr_t *)0); - } - retval = read(fd, def_sub_area, (int) statbuf.st_size); - /* - "Upon successful completion, read and readv return the number - of bytes actually read and placed in the buffer. The system - guarantees to read the number of bytes requested if the - descriptor references a normal file that has that many bytes - left before the end-of-file, but in no other case." - -- read(2) - Therefore, the following test is valid. - */ - if (retval != statbuf.st_size) { - syslog(LOG_ERR, "short read in copy_def_subs"); - (void) close(fd); - return((ZSubscr_t *)0); - } - - (void) close(fd); - def_sub_area[statbuf.st_size] = '\0'; /* null-terminate it */ - - /* - def_subs_area now points to a buffer full of subscription - info. - each line of the stuff is of the form: - class,inst,recipient - - Commas and newlines may not appear as part of the class, - instance, or recipient. XXX! - */ - - /* split up the subscription info */ - for (cp = def_sub_area; - cp < def_sub_area + statbuf.st_size; - cp++) - if ((*cp == '\n') || (*cp == ',')) - *cp = '\0'; - default_notice.z_message = def_sub_area; - default_notice.z_message_len = (int) statbuf.st_size + 1; - default_notice.z_auth = 1; - defaults_read = 1; - } - /* needed later for access_check() */ - default_notice.z_sender = person; - subs = extract_subscriptions(&default_notice); - /* replace any non-* recipients with "person" */ - - for (subs2 = subs->q_forw; subs2 != subs; subs2 = subs2->q_forw) { - /* if not a wildcard, replace it with person */ - if (strcmp(subs2->zst_dest.recip->string, "*")) { - free_zstring(subs2->zst_dest.recip); - subs2->zst_dest.recip = make_zstring(person,0); - } else { /* replace with null recipient */ - free_zstring(subs2->zst_dest.recip); - subs2->zst_dest.recip = dup_zstring(empty); - } - set_ZDestination_hash(&(subs2->zst_dest)); - } - return(subs); -} - -/* - * Cancel one subscription. - */ - -Code_t -subscr_cancel(sin, notice) - struct sockaddr_in *sin; - ZNotice_t *notice; -{ - ZClient_t *who; - register ZSubscr_t *subs, *subs2, *subs3, *subs4; - Code_t retval; - int found = 0; - int relation; - -#if 0 - zdbug((LOG_DEBUG,"subscr_cancel")); -#endif - if (!(who = client_which_client(sin, notice))) - return(ZSRV_NOCLT); - - if (!who->zct_subs) - return(ZSRV_NOSUB); - - if (!(subs = extract_subscriptions(notice))) - return(ZERR_NONE); /* no subscr -> no error */ - - START_CRITICAL_CODE; - - for (subs4 = subs->q_forw; subs4 != subs; subs4 = subs4->q_forw) { - for (subs2 = who->zct_subs->q_forw; - subs2 != who->zct_subs;) { - /* for each existing subscription */ - /* is this what we are canceling? */ - relation = compare_subs(subs2, subs4,0); - if (relation < 0) { - subs2 = subs2->q_forw; - continue; - } - if (relation > 0) - /* We have passed last possible one */ - break; - - /* go back, since remque will change things */ - subs3 = subs2->q_back; - xremque(subs2); - (void) class_deregister(who, subs2); - free_zstring(subs2->zst_dest.classname); - free_zstring(subs2->zst_dest.inst); - free_zstring(subs2->zst_dest.recip); - xfree(subs2); - found = 1; - /* now that the remque adjusted the linked - list, we go forward again */ - subs2 = subs3->q_forw; - break; - } - } - - /* make sure we are still registered for all the classes */ - if (found) { - for (subs2 = who->zct_subs->q_forw; - subs2 != who->zct_subs; - subs2 = subs2->q_forw) - if ((retval = class_register(who, subs2)) != ZERR_NONE) { - free_subscriptions(subs); - END_CRITICAL_CODE; - return(retval); - } - } - - END_CRITICAL_CODE; - - free_subscriptions(subs); - if (found) { -#if 0 - zdbug((LOG_DEBUG, "found & removed")); -#endif - return(ZERR_NONE); - } else { -#if 0 - zdbug((LOG_DEBUG, "not found")); -#endif - return(ZSRV_NOSUB); - } -} - -/* - * Cancel all the subscriptions for this client. - */ - -void -subscr_cancel_client(client) - ZClient_t *client; -{ - register ZSubscr_t *subs; - -#if 0 - zdbug((LOG_DEBUG,"subscr_cancel_client %s", - inet_ntoa (client->zct_addr.sin_addr))); -#endif - if (!client->zct_subs) - return; - - START_CRITICAL_CODE; - - for (subs = client->zct_subs->q_forw; - subs != client->zct_subs; - subs = client->zct_subs->q_forw) { -#if 0 - zdbug((LOG_DEBUG,"sub_can %s", - subs->zst_dest.classname->string)); -#endif - if (class_deregister(client, subs) != ZERR_NONE) { -#if 0 - zdbug((LOG_DEBUG,"sub_can_clt: not registered!")); -#endif - } - xremque(subs); - free_zstring(subs->zst_dest.classname); - free_zstring(subs->zst_dest.inst); - free_zstring(subs->zst_dest.recip); - xfree(subs); - } - - /* also flush the head of the queue */ - /* subs is now client->zct_subs */ - free_zstring(subs->zst_dest.classname); - free_zstring(subs->zst_dest.inst); - free_zstring(subs->zst_dest.recip); - xfree(subs); - client->zct_subs = NULLZST; - - END_CRITICAL_CODE; - - return; -} - -#ifdef notdef -/* not used for the moment */ -/* - * Cancel all the subscriptions for clients at this addr. - */ - -Code_t -subscr_cancel_host(addr) -struct in_addr *addr; -{ - register ZHostList_t *hosts; - register ZClientList_t *clist = NULLZCLT, *clt; - - /* find the host */ - if (!(hosts = hostm_find_host(addr))) - return(ZSRV_HNOTFOUND); - clist = hosts->zh_clients; - - START_CRITICAL_CODE; - - /* flush each one */ - for (clt = clist->q_forw; clt != clist; clt = clt->q_forw) - (void) subscr_cancel_client(clt->zclt_client); - - END_CRITICAL_CODE; - - return(ZERR_NONE); -} -#endif - -/* - * Here is the bulk of the work in the subscription manager. - * We grovel over the list of clients possibly interested in this - * notice, and copy into a list on a match. Make sure we only add any given - * client once. - */ - -ZClientList_t * -subscr_match_list(notice) - ZNotice_t *notice; -{ - register ZClientList_t *hits, *clients, *majik, *clients2, *hit2; - char *saveclass, *saveclinst; - ZSTRING *newclass; - ZSTRING *newclinst; - ZSubscr_t check_sub; - - if (!(hits = (ZClientList_t *) xmalloc(sizeof(ZClientList_t)))) - return(NULLZCLT); - hits->q_forw = hits->q_back = hits; - - saveclass = notice->z_class; - newclass = make_zstring(notice->z_class, 1); - - saveclinst = notice->z_class_inst; - newclinst = make_zstring(notice->z_class_inst, 1); - - check_sub.zst_dest.classname = newclass; - check_sub.zst_dest.inst = newclinst; - check_sub.zst_dest.recip = make_zstring(notice->z_recipient, 0); - set_ZDestination_hash(&check_sub.zst_dest); - check_sub.q_forw = check_sub.q_back = &check_sub; - - clients = class_lookup (&check_sub); - majik = class_lookup (&matchall_sub); - if (!clients && !majik) - return NULLZCLT; - - notice->z_class = (char *) newclass->string; - notice->z_class_inst = (char *) newclinst->string; - if (clients) { - for (clients2 = clients->q_forw; - clients2 != clients; - clients2 = clients2->q_forw) - if (cl_match(&check_sub, clients2->zclt_client)) { - if (!clt_unique(clients2->zclt_client, hits)) - continue; - /* we hit */ - if (!(hit2 = (ZClientList_t *) xmalloc(sizeof(ZClientList_t)))) { - syslog(LOG_WARNING, - "subscr_match: punting/no mem"); - notice->z_class = saveclass; - notice->z_class_inst = saveclinst; - free_zstring(newclass); - free_zstring(newclinst); - free_zstring(check_sub.zst_dest.recip); - return(hits); - } - hit2->zclt_client = clients2->zclt_client; - hit2->q_forw = hit2->q_back = hit2; - xinsque(hit2, hits); - } - class_free(clients); - } - if (majik) { - for (clients2 = majik->q_forw; - clients2 != majik; - clients2 = clients2->q_forw) { - if (!clt_unique(clients2->zclt_client, hits)) - continue; - /* we hit */ - if (!(hit2 = (ZClientList_t *) xmalloc(sizeof(ZClientList_t)))) { - syslog(LOG_WARNING, - "subscr_match(majik): punting/no mem"); - notice->z_class = saveclass; - notice->z_class_inst = saveclinst; - free_zstring(newclass); - free_zstring(newclinst); - free_zstring(check_sub.zst_dest.recip); - return(hits); - } - hit2->zclt_client = clients2->zclt_client; - hit2->q_forw = hit2->q_back = hit2; - - xinsque(hit2, hits); - } - class_free(majik); - } - notice->z_class = saveclass; - notice->z_class_inst = saveclinst; - free_zstring(newclass); - free_zstring(newclinst); - free_zstring(check_sub.zst_dest.recip); - if (hits->q_forw == hits) { - xfree(hits); - return(NULLZCLT); - } - return(hits); -} - -/* - * Free memory used by a list we allocated. - */ - -void -subscr_free_list(list) - ZClientList_t *list; -{ - register ZClientList_t *lyst; - - for (lyst = list->q_forw; lyst != list; lyst = list->q_forw) { - xremque(lyst); - xfree(lyst); - } - xfree(list); - return; -} - -/* - * Send the requester a list of his current subscriptions - */ - -void -subscr_sendlist(notice, auth, who) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; -{ - char **answer; - int found; - struct sockaddr_in send_to_who; - Code_t retval; - -#ifdef OLD_COMPAT - if (!strcmp(notice->z_version, OLD_ZEPHYR_VERSION)) { - /* we are talking to an old client; use the old-style - acknowledgement-message */ - old_compat_subscr_sendlist(notice, auth, who); - return; - } -#endif /* OLD_COMPAT */ -#ifdef NEW_COMPAT - if (!strcmp(notice->z_version, NEW_OLD_ZEPHYR_VERSION)) { - /* we are talking to a new old client; use the new-old-style - acknowledgement-message */ - new_old_compat_subscr_sendlist(notice, auth, who); - return; - } -#endif /* NEW_COMPAT */ - answer = subscr_marshal_subs(notice, auth, who, &found); - send_to_who = *who; - send_to_who.sin_port = notice->z_port; /* Return port */ - - if ((retval = ZSetDestAddr(&send_to_who)) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_sendlist set addr: %s", - error_message(retval)); - if (answer) - xfree(answer); - return; - } - - /* XXX for now, don't do authentication */ - auth = 0; - - notice->z_kind = ACKED; - - /* use xmit_frag() to send each piece of the notice */ - - if ((retval = ZSrvSendRawList(notice, (char **) answer, - found*NUM_FIELDS, xmit_frag)) - != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_sendlist xmit: %s", - error_message(retval)); - } - if (answer) - xfree(answer); - return; -} - -static char ** -subscr_marshal_subs(notice, auth, who, found) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - register int *found; -{ - ZNotice_t reply; - char **answer = (char **) 0; - int temp; - Code_t retval; - ZClient_t *client; - register ZSubscr_t *subs, *subs2 = NULLZST; - register int i; - int defsubs = 0; - -#if 0 - zdbug((LOG_DEBUG, "subscr_marshal")); -#endif - *found = 0; - - /* Note that the following code is an incredible crock! */ - - /* We cannot send multiple packets as acknowledgements to the client, - since the hostmanager will ignore the later packets. So we need - to send directly to the client. */ - - /* Make our own copy so we can send directly back to the client */ - /* RSF 11/07/87 */ - - - if (!strcmp(notice->z_opcode, CLIENT_GIMMESUBS)) { - /* If the client has requested his current subscriptions, - the message field of the notice contains the port number - of the client for which the sender desires the subscription - list. The port field is the port of the sender. */ - - if ((retval = ZReadAscii(notice->z_message, - notice->z_message_len, - (unsigned char *)&temp, - sizeof(u_short))) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_marshal read port num: %s", - error_message(retval)); - return((char **)0); - } - - /* Blech blech blech */ - reply = *notice; - reply.z_port = *((u_short *)&temp); - - client = client_which_client(who, &reply); - - if (client) - subs2 = client->zct_subs; - } else if (!strcmp(notice->z_opcode, CLIENT_GIMMEDEFS)) { -#if 0 - zdbug((LOG_DEBUG, "gimmedefs")); -#endif - /* subscr_copy_def_subs allocates new pointer rings, so - it must be freed when finished. - the string areas pointed to are static, however.*/ - subs2 = subscr_copy_def_subs(notice->z_sender); - defsubs = 1; - } else { - syslog(LOG_ERR, "subscr_marshal bogus opcode %s", - notice->z_opcode); - return((char **) 0); - } - - if (subs2) { - - /* check authenticity here. The user must be authentic to get - a list of subscriptions. If he is not subscribed to - anything, this if-clause fails, and he gets a response - indicating no subscriptions. - if retrieving default subscriptions, don't care about - authentication. */ - - if (!auth && !defsubs) { - return((char **) 0); - } - if (!defsubs) { - if (client && (strcmp(client->zct_principal->string, - notice->z_sender) != 0)) { - zdbug ((LOG_DEBUG, - "subscr_marshal: %s requests subs for %s at %s/%d", - notice->z_sender, - client->zct_principal->string, - inet_ntoa (who->sin_addr), - ntohs (who->sin_port))); - return 0; - } - } - - for (subs = subs2->q_forw; - subs != subs2; - subs = subs->q_forw, (*found)++); - - /* found is now the number of subscriptions */ - - /* coalesce the subscription information into a list of - char *'s */ - if ((answer = (char **) xmalloc((*found) * NUM_FIELDS * sizeof(char *))) == (char **) 0) { - syslog(LOG_ERR, "subscr no mem(answer)"); - *found = 0; - } else - for (i = 0, subs = subs2->q_forw; - i < *found ; - i++, subs = subs->q_forw) { - answer[i*NUM_FIELDS] = subs->zst_dest.classname->string; - answer[i*NUM_FIELDS + 1] = subs->zst_dest.inst->string; - answer[i*NUM_FIELDS + 2] = subs->zst_dest.recip->string; - } - } - if (defsubs) - free_subscriptions(subs2); - return(answer); -} - -#ifdef NEW_COMPAT -static void -new_old_compat_subscr_sendlist(notice, auth, who) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; -{ - Code_t retval; - ZNotice_t reply; - ZPacket_t reppacket; - int packlen, found, count, initfound, zerofound; - char buf[64]; - Zconst char **answer; - struct sockaddr_in send_to_who; - register int i; - - new_compat_count_subscr++; - - syslog(LOG_INFO, "new old subscr, %s", inet_ntoa(who->sin_addr)); - reply = *notice; - reply.z_kind = SERVACK; - reply.z_authent_len = 0; /* save some space */ - reply.z_auth = 0; - - send_to_who = *who; - send_to_who.sin_port = notice->z_port; /* Return port */ - - if ((retval = ZSetDestAddr(&send_to_who)) != ZERR_NONE) { - syslog(LOG_WARNING, "new_old_subscr_sendlist set addr: %s", - error_message(retval)); - return; - } - - /* retrieve the subscriptions */ - answer = subscr_marshal_subs(notice, auth, who, &found); - - /* note that when there are no subscriptions, found == 0, so - we needn't worry about answer being NULL since - ZFormatSmallRawNoticeList won't reference the pointer */ - - /* send 5 at a time until we are finished */ - count = found?((found-1) / 5 + 1):1; /* total # to be sent */ - i = 0; /* pkt # counter */ -#if 0 - zdbug((LOG_DEBUG,"Found %d subscriptions for %d packets", - found,count)); -#endif - initfound = found; - zerofound = (found == 0); - while (found > 0 || zerofound) { - packlen = sizeof(reppacket); - (void) sprintf(buf, "%d/%d", ++i, count); - reply.z_opcode = buf; - retval = ZFormatSmallRawNoticeList(&reply, - answer+(initfound-found)*NUM_FIELDS, - ((found > 5) ? 5 : found)*NUM_FIELDS, - reppacket, - &packlen); - if (retval != ZERR_NONE) { - syslog(LOG_ERR, "subscr_sendlist format: %s", - error_message(retval)); - if (answer) - xfree(answer); - return; - } - if ((retval = ZSendPacket(reppacket, packlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_sendlist xmit: %s", - error_message(retval)); - if (answer) - xfree(answer); - return; - } - found -= 5; - zerofound = 0; - } -#if 0 - zdbug((LOG_DEBUG,"subscr_sendlist acked")); -#endif - if (answer) - xfree(answer); - return; -} -#endif /* NEW_COMPAT */ - -#ifdef OLD_COMPAT -static void -old_compat_subscr_sendlist(notice, auth, who) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; -{ - ZClient_t *client = client_which_client(who, notice); - register ZSubscr_t *subs; - Code_t retval; - ZNotice_t reply; - ZPacket_t reppacket; - int packlen, i, found = 0; - char **answer = (char **) NULL; - - old_compat_count_subscr++; - - syslog(LOG_INFO, "old old subscr, %s", inet_ntoa(who->sin_addr)); - if (client && client->zct_subs) { - - /* check authenticity here. The user must be authentic to get - a list of subscriptions. If he is not subscribed to - anything, the above test fails, and he gets a response - indicating no subscriptions */ - - if (!auth) { - clt_ack(notice, who, AUTH_FAILED); - return; - } - - for (subs = client->zct_subs->q_forw; - subs != client->zct_subs; - subs = subs->q_forw, found++); - - /* found is now the number of subscriptions */ - - /* coalesce the subscription information into a list of - char *'s */ - if ((answer = (char **) xmalloc(found * NUM_FIELDS * sizeof(char *))) == (char **) 0) { - syslog(LOG_ERR, "old_subscr_sendlist no mem(answer)"); - found = 0; - } else - for (i = 0, subs = client->zct_subs->q_forw; - i < found ; - i++, subs = subs->q_forw) { - answer[i*NUM_FIELDS] = subs->zst_class; - answer[i*NUM_FIELDS + 1] = subs->zst_classinst; - answer[i*NUM_FIELDS + 2] = subs->zst_recipient; - } - } - /* note that when there are no subscriptions, found == 0, so - we needn't worry about answer being NULL */ - - reply = *notice; - reply.z_kind = SERVACK; - reply.z_authent_len = 0; /* save some space */ - reply.z_auth = 0; - - - /* if it's too long, chop off one at a time till it fits */ - while ((retval = ZFormatSmallRawNoticeList(&reply, - answer, - found * NUM_FIELDS, - reppacket, - &packlen)) == ZERR_PKTLEN) { - found--; - reply.z_opcode = OLD_CLIENT_INCOMPSUBS; - } - if (retval != ZERR_NONE) { - syslog(LOG_ERR, "old_subscr_sendlist format: %s", - error_message(retval)); - if (answer) - xfree(answer); - return; - } - if ((retval = ZSetDestAddr(who)) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_sendlist set addr: %s", - error_message(retval)); - if (answer) - xfree(answer); - return; - } - if ((retval = ZSendPacket(reppacket, packlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_sendlist xmit: %s", - error_message(retval)); - if (answer) - xfree(answer); - return; - } -#if 0 - zdbug((LOG_DEBUG,"subscr_sendlist acked")); -#endif - if (answer) - xfree(answer); - return; -} -#endif /* OLD_COMPAT */ - -/* - * Send the client's subscriptions to another server - */ - -/* version is currently unused; if necessary later versions may key off it - to determine what to send to the peer (protocol changes) */ - -/*ARGSUSED*/ -Code_t -subscr_send_subs(client, vers) - ZClient_t *client; - char *vers; -{ - register int i = 0; - register ZSubscr_t *sub; -#ifdef KERBEROS - char buf[512]; - C_Block cblock; -#endif /* KERBEROS */ - char buf2[512]; - char *lyst[7 * NUM_FIELDS]; - int num = 0; - Code_t retval; - -#if 0 - zdbug((LOG_DEBUG, "send_subs")); -#endif - (void) sprintf(buf2, "%d",ntohs(client->zct_sin.sin_port)); - - lyst[num++] = buf2; - -#ifdef KERBEROS -#ifdef NOENCRYPTION - (void) memcpy((caddr_t)cblock, (caddr_t)client->zct_cblock, sizeof(C_Block)); -#else - des_ecb_encrypt(client->zct_cblock, cblock, serv_ksched.s, DES_ENCRYPT); -#endif - - if ((retval = ZMakeAscii(buf, sizeof(buf), cblock, - sizeof(C_Block))) != ZERR_NONE) { -#if 0 - zdbug((LOG_DEBUG,"zmakeascii failed: %s", - error_message(retval))); -#endif - } else { - lyst[num++] = buf; -#if 0 - zdbug((LOG_DEBUG,"cblock %s",buf)); -#endif - } -#endif /* KERBEROS */ - if ((retval = bdump_send_list_tcp(SERVACK, client->zct_sin.sin_port, - ZEPHYR_ADMIN_CLASS, - num > 1 ? "CBLOCK" : "", - ADMIN_NEWCLT, - (char*)client->zct_principal->string, - "", lyst, num)) != ZERR_NONE ) { - syslog(LOG_ERR, "subscr_send_subs newclt: %s", - error_message(retval)); - return(retval); - } - - if (!client->zct_subs) - return(ZERR_NONE); - for (sub = client->zct_subs->q_forw; - sub != client->zct_subs; - sub = sub->q_forw) { - /* for each subscription */ - lyst[i * NUM_FIELDS] = sub->zst_dest.classname->string; - lyst[i * NUM_FIELDS + 1] = sub->zst_dest.inst->string; - lyst[i * NUM_FIELDS + 2] = sub->zst_dest.recip->string; - i++; - if (i >= 7) { - /* we only put 7 in each packet, so we don't - run out of room */ - if ((retval = bdump_send_list_tcp(ACKED, - client->zct_sin.sin_port, - ZEPHYR_CTL_CLASS, "", - CLIENT_SUBSCRIBE, "", - "", lyst, - i * NUM_FIELDS)) - != ZERR_NONE) { - syslog(LOG_ERR, "subscr_send_subs subs: %s", - error_message(retval)); - return(retval); - } - i = 0; - } - } - if (i) { - if ((retval = bdump_send_list_tcp(ACKED, - client->zct_sin.sin_port, - ZEPHYR_CTL_CLASS, "", - CLIENT_SUBSCRIBE, "", "", - lyst, i * NUM_FIELDS)) - != ZERR_NONE) { - syslog(LOG_ERR, "subscr_send_subs subs: %s", - error_message(retval)); - return(retval); - } - } - return(ZERR_NONE); -} - -/* - * is this client unique to this list? 0 = no, 1 = yes - */ - -static int -clt_unique(clt, clist) - ZClient_t *clt; - ZClientList_t *clist; -{ - register ZClientList_t *client; - - for (client = clist->q_forw; - client != clist; - client = client->q_forw) - if (client->zclt_client == clt) - return(0); - return(1); -} - -/* - * is this client listening to this notice? 1=yes, 0=no - */ - -static int -cl_match(notice_subs, client) - register ZSubscr_t *notice_subs; - register ZClient_t *client; -{ - register ZSubscr_t *subs; - int relation; - - if (client->zct_subs == NULLZST) { - syslog(LOG_WARNING, "cl_match w/ no subs"); - return(0); - } - - for (subs = client->zct_subs->q_forw; - subs != client->zct_subs; - subs = subs->q_forw) { - relation = compare_subs(notice_subs, subs, 1); - -/* - if (relation < 0) - return(0); -*/ - if (relation == 0) - return(1); - } - /* fall through */ - return(0); -} - -/* - * free the memory allocated for the list of subscriptions. - */ - -static void -free_subscriptions(subs) - register ZSubscr_t *subs; -{ - register ZSubscr_t *sub; - - for (sub = subs->q_forw; sub != subs; sub = subs->q_forw) { - xremque(sub); - free_zstring(sub->zst_dest.classname); - free_zstring(sub->zst_dest.inst); - free_zstring(sub->zst_dest.recip); - xfree(sub); - } - free_zstring(subs->zst_dest.classname); - free_zstring(subs->zst_dest.inst); - free_zstring(subs->zst_dest.recip); - xfree(subs); - - return; -} - -#define ADVANCE(xx) { cp += (strlen(cp) + 1); \ - if (cp >= notice->z_message + notice->z_message_len) { \ - syslog(LOG_WARNING, "malformed subscription %d", xx); \ - return(subs); \ - }} - -/* - * Parse the message body, returning a linked list of subscriptions, or - * NULLZST if there are no subscriptions there. - */ - -static ZSubscr_t * -extract_subscriptions(notice) - register ZNotice_t *notice; -{ - register ZSubscr_t *subs = NULLZST, *subs2; - register char *recip, *class_name, *classinst; - register char *cp = notice->z_message; - - /* parse the data area for the subscriptions */ - while (cp < notice->z_message + notice->z_message_len) { - class_name = cp; - if (*cp == '\0') - /* we've exhausted the subscriptions */ - return(subs); - ADVANCE(1); - classinst = cp; - ADVANCE(2); - recip = cp; -#if 0 - zdbug((LOG_DEBUG, "ext_sub: CLS %s INST %s RCPT %s", - class_name, classinst, cp)); -#endif - cp += (strlen(cp) + 1); - if (cp > notice->z_message + notice->z_message_len) { - syslog(LOG_WARNING, "malformed sub 3"); - return(subs); - } - if (!subs) { - if (!(subs = (ZSubscr_t *) - xmalloc(sizeof(ZSubscr_t)))) { - syslog(LOG_WARNING, "ex_subs: no mem"); - return(NULLZST); - } - subs->q_forw = subs->q_back = subs; - subs->zst_dest.classname = subs->zst_dest.inst = - subs->zst_dest.recip = NULL; - subs->zst_dest.hash_value = 0; - } - if (!(subs2 = (ZSubscr_t *) xmalloc(sizeof(ZSubscr_t)))) { - syslog(LOG_WARNING, "ex_subs: no mem 2"); - return(subs); - } - subs2->q_forw = subs2->q_back = subs2; - subs2->zst_dest.classname = make_zstring(class_name,1); - subs2->zst_dest.inst = make_zstring(classinst,1); - subs2->zst_dest.recip = make_zstring(recip,0); - set_ZDestination_hash(&subs2->zst_dest); - - xinsque(subs2, subs); - } - return(subs); -} - -/* - * print subscriptions in subs onto fp. - * assumed to be called with SIGFPE blocked - * (true if called from signal handler) - */ - -void -subscr_dump_subs(fp, subs) - FILE *fp; - ZSubscr_t *subs; -{ - register ZSubscr_t *ptr; - - if (!subs) /* no subscriptions to dump */ - return; - - for (ptr = subs->q_forw; ptr != subs; ptr = ptr->q_forw) { - fputs("\t\t'", fp); - fputs(ptr->zst_dest.classname->string, fp); - fputs("' '", fp); - fputs(ptr->zst_dest.inst->string, fp); - fputs("' '", fp); - fputs(ptr->zst_dest.recip->string, fp); - fputs("'\n", fp); - } - return; -} - -int -compare_subs(s1,s2,do_wildcard) - ZSubscr_t *s1, *s2; - int do_wildcard; -{ - -#if 0 - zdbug((LOG_DEBUG,"compare_subs: %s/%s/%s to %s/%s/%s", - s1->zst_dest.classname->string, s1->zst_dest.inst->string, s1->zst_dest.recip->string, - s2->zst_dest.classname->string, s2->zst_dest.inst->string, s2->zst_dest.recip->string)); -#endif - /* wildcard must be in s2 in order for it to match */ - - if (do_wildcard && (s1->zst_dest.classname == s2->zst_dest.classname) && - (s2->zst_dest.inst == wildcard_instance) && - (s1->zst_dest.recip == s2->zst_dest.recip)) - return(0); - - if (s1->zst_dest.hash_value > s2->zst_dest.hash_value) - return 1; - if (s1->zst_dest.hash_value < s2->zst_dest.hash_value) - return -1; - - if (s1->zst_dest.classname != s2->zst_dest.classname) - return(strcasecmp(s1->zst_dest.classname->string, - s2->zst_dest.classname->string)); - - if (s1->zst_dest.inst != s2->zst_dest.inst) - return(strcasecmp(s1->zst_dest.inst->string, - s2->zst_dest.inst->string)); - - if (s1->zst_dest.recip != s2->zst_dest.recip) - return(strcasecmp(s1->zst_dest.recip->string, - s2->zst_dest.recip->string)); - - return(0); -} - -static void -check_sub_order(subs,wc) - ZSubscr_t *subs; - int wc; -{ - ZSubscr_t *subs2; - int relation; - - for (subs2 = subs->q_forw; - subs2->q_forw != subs; - subs2 = subs2->q_forw) { - - /* for each existing subscription */ - relation = compare_subs(subs2,subs2->q_forw,wc); - if (relation > 0) { - syslog(LOG_DEBUG, "s_check failed: %s/%s/%s <=> %s/%s/%s = %d", - subs2->zst_dest.classname->string, - subs2->zst_dest.inst->string, - subs2->zst_dest.recip->string, - subs2->q_forw->zst_dest.classname->string, - subs2->q_forw->zst_dest.inst->string, - subs2->q_forw->zst_dest.recip->string, - relation); - } - - } -} diff --git a/server/timer.c b/server/timer.c index 9d59cba..d23eb82 100644 --- a/server/timer.c +++ b/server/timer.c @@ -9,10 +9,12 @@ * */ +#include "zserver.h" + #ifndef SABER #ifndef lint -static char rcsid[] = - "$Id$"; +static const char rcsid[] = +"$Id$"; #endif /* lint */ #endif /* SABER */ @@ -24,46 +26,43 @@ static char rcsid[] = * Massachusetts Institute of Technology * * written by Ken Raeburn - -Permission to use, copy, modify, and distribute this -software and its documentation for any purpose and without -fee is hereby granted, provided that the above copyright -notice appear in all copies and that both that copyright -notice and this permission notice appear in supporting -documentation, and that the name of M.I.T. and the Student -Information Processing Board not be used in -advertising or publicity pertaining to distribution of the -software without specific, written prior permission. -M.I.T. and the Student Information Processing Board -make no representations about the suitability of -this software for any purpose. It is provided "as is" -without express or implied warranty. - + + Permission to use, copy, modify, and distribute this + software and its documentation for any purpose and without + fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright + notice and this permission notice appear in supporting + documentation, and that the name of M.I.T. and the Student + Information Processing Board not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + M.I.T. and the Student Information Processing Board + make no representations about the suitability of + this software for any purpose. It is provided "as is" + without express or implied warranty. + */ /* * External functions: * - * timer timer_set_rel (time_rel, proc, arg) + * Timer *timer_set_rel (time_rel, proc, arg) * long time_rel; * void (*proc)(); * caddr_t arg; - * timer timer_set_abs (time_abs, proc, arg) + * Timer *timer_set_abs (time_abs, proc, arg) * long time_abs; * void (*proc)(); * caddr_t arg; * * void timer_reset(tmr) - * timer tmr; + * Timer *tmr; * * void timer_process() * */ -#include <stdio.h> -#include "zserver.h" - /* DELTA is just an offset to keep the size a bit less than a power * of two. It's measured in pointers, so it's 32 bytes on most * systems. */ @@ -109,180 +108,149 @@ without express or implied warranty. #define PARENT(i) (((i) - 1) / 2) #define CHILD1(i) ((i) * 2 + 1) #define CHILD2(i) ((i) * 2 + 2) -#define TIME(i) (heap[i]->time) +#define TIME(i) (heap[i]->abstime) #define HEAP_ASSIGN(pos, tmr) ((heap[pos] = (tmr))->heap_pos = (pos)) -long nexttimo = 0L; /* the Unix time of the next - alarm */ -static timer *heap; +static Timer **heap; static int num_timers = 0; static int heap_size = 0; -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -static void timer_botch P((void*)); -static timer add_timer P((timer)); - -/* - * timer_set_rel(time_rel, proc) - * time_rel: alarm time relative to now, in seconds - * proc: subroutine to be called (no args, returns void) - * - * creates a "timer" and adds it to the current list, returns "timer" - */ +static void timer_botch __P((void*)); +static Timer *add_timer __P((Timer *)); -timer timer_set_rel (time_rel, proc, arg) - long time_rel; - void (*proc) P((void *)); - void *arg; +Timer *timer_set_rel(time_rel, proc, arg) + long time_rel; + void (*proc) __P((void *)); + void *arg; { - timer new_t; - new_t = (timer) xmalloc(sizeof(*new_t)); - if (new_t == NULL) - return(NULL); - new_t->time = time_rel + NOW; - new_t->func = proc; - new_t->arg = arg; - return add_timer(new_t); + Timer *new_t; + + new_t = (Timer *) malloc(sizeof(*new_t)); + if (new_t == NULL) + return(NULL); + new_t->abstime = time_rel + NOW; + new_t->func = proc; + new_t->arg = arg; + return add_timer(new_t); } -/* - * timer_reset - * - * args: - * tmr: timer to be removed from the list - * - * removes any timers matching tmr and reallocates list - * - */ - void timer_reset(tmr) - timer tmr; + Timer *tmr; { - int pos, min; - - /* Free the timer, saving its heap position. */ - pos = tmr->heap_pos; - xfree(tmr); - - if (pos != num_timers - 1) { - /* Replace the timer with the last timer in the heap and - * restore the heap, propagating the timer either up or - * down, depending on which way it violates the heap - * property to insert the last timer in place of the - * deleted timer. */ - if (pos > 0 && TIME(num_timers - 1) < TIME(PARENT(pos))) { - do { - HEAP_ASSIGN(pos, heap[PARENT(pos)]); - pos = PARENT(pos); - } while (pos > 0 && TIME(num_timers - 1) < TIME(PARENT(pos))); - HEAP_ASSIGN(pos, heap[num_timers - 1]); - } else { - while (CHILD2(pos) < num_timers) { - min = num_timers - 1; - if (TIME(CHILD1(pos)) < TIME(min)) - min = CHILD1(pos); - if (TIME(CHILD2(pos)) < TIME(min)) - min = CHILD2(pos); - HEAP_ASSIGN(pos, heap[min]); - pos = min; - } - if (pos != num_timers - 1) - HEAP_ASSIGN(pos, heap[num_timers - 1]); + int pos, min; + + /* Free the timer, saving its heap position. */ + pos = tmr->heap_pos; + free(tmr); + + if (pos != num_timers - 1) { + /* Replace the timer with the last timer in the heap and + * restore the heap, propagating the timer either up or + * down, depending on which way it violates the heap + * property to insert the last timer in place of the + * deleted timer. */ + if (pos > 0 && TIME(num_timers - 1) < TIME(PARENT(pos))) { + do { + HEAP_ASSIGN(pos, heap[PARENT(pos)]); + pos = PARENT(pos); + } while (pos > 0 && TIME(num_timers - 1) < TIME(PARENT(pos))); + HEAP_ASSIGN(pos, heap[num_timers - 1]); + } else { + while (CHILD2(pos) < num_timers) { + min = num_timers - 1; + if (TIME(CHILD1(pos)) < TIME(min)) + min = CHILD1(pos); + if (TIME(CHILD2(pos)) < TIME(min)) + min = CHILD2(pos); + HEAP_ASSIGN(pos, heap[min]); + pos = min; } + if (pos != num_timers - 1) + HEAP_ASSIGN(pos, heap[num_timers - 1]); } - num_timers--; - - /* Fix up the next timeout. */ - nexttimo = (num_timers == 0) ? 0 : heap[0]->time; + } + num_timers--; } #define set_timeval(t,s) ((t).tv_sec=(s),(t).tv_usec=0,(t)) -/* add_timer(t:timer) - * - * args: - * t: new "timer" to be added - * - * returns: - * 0 if successful - * -1 if error (errno set) -- old time table may have been destroyed - * - */ -static timer +static Timer * add_timer(new) - timer new; + Timer *new; { - int pos; - - /* Create or resize the heap as necessary. */ - if (heap_size == 0) { - heap_size = INITIAL_HEAP_SIZE; - heap = (timer *) xmalloc(heap_size * sizeof(timer)); - } else if (num_timers >= heap_size) { - heap_size = heap_size * 2 + DELTA; - heap = (timer *) xrealloc(heap, heap_size * sizeof(timer)); - } - if (!heap) { - xfree(new); - return NULL; - } - - /* Insert the timer into the heap. */ - pos = num_timers; - while (pos > 0 && new->time < TIME(PARENT(pos))) { - HEAP_ASSIGN(pos, heap[PARENT(pos)]); - pos = PARENT(pos); - } - HEAP_ASSIGN(pos, new); - num_timers++; - - /* Fix up the next timeout. */ - nexttimo = heap[0]->time; - return new; + int pos; + + /* Create or resize the heap as necessary. */ + if (heap_size == 0) { + heap_size = INITIAL_HEAP_SIZE; + heap = (Timer **) malloc(heap_size * sizeof(Timer *)); + } else if (num_timers >= heap_size) { + heap_size = heap_size * 2 + DELTA; + heap = (Timer **) realloc(heap, heap_size * sizeof(Timer *)); + } + if (!heap) { + free(new); + return NULL; + } + + /* Insert the Timer *into the heap. */ + pos = num_timers; + while (pos > 0 && new->abstime < TIME(PARENT(pos))) { + HEAP_ASSIGN(pos, heap[PARENT(pos)]); + pos = PARENT(pos); + } + HEAP_ASSIGN(pos, new); + num_timers++; + + return new; } -/* - * timer_process -- checks for next timer execution time - * and execute - * - */ - void timer_process() { - register timer t; - timer_proc func; - void *arg; - int valid = 0; - - if (num_timers == 0 || heap[0]->time > NOW) - return; - - /* Remove the first timer from the heap, remembering it's - * function and argument. timer_reset() updates nexttimo. */ - t = heap[0]; - func = t->func; - arg = t->arg; - t->func = timer_botch; - t->arg = NULL; - timer_reset(t); + Timer *t; + timer_proc func; + void *arg; + int valid = 0; + + if (num_timers == 0 || heap[0]->abstime > NOW) + return; + + /* Remove the first timer from the heap, remembering its + * function and argument. */ + t = heap[0]; + func = t->func; + arg = t->arg; + t->func = timer_botch; + t->arg = NULL; + timer_reset(t); + + /* Run the function. */ + func(arg); +} - /* Run the function. */ - (func)(arg); +struct timeval * +timer_timeout(tvbuf) + struct timeval *tvbuf; +{ + if (num_timers > 0) { + tvbuf->tv_sec = heap[0]->abstime - NOW; + if (tvbuf->tv_sec < 0) + tvbuf->tv_sec = 0; + tvbuf->tv_usec = 0; + return tvbuf; + } else { + return NULL; + } } static void timer_botch(arg) - void *arg; + void *arg; { - syslog(LOG_CRIT, "Timer botch\n"); - abort(); + syslog(LOG_CRIT, "timer botch\n"); + abort(); } diff --git a/server/timer.h b/server/timer.h index 231208f..42c0081 100644 --- a/server/timer.h +++ b/server/timer.h @@ -6,11 +6,12 @@ * * $Source$ * $Author$ - * $Header: /mit/zephyr/src/server/RCS/timer.h,v 1.9 94/03/15 12:44:40 prob -e Exp $ + * $Header$ * */ +#ifndef __TIMER_H + /* * timer_manager_ -- routines for handling timers in login_shell * (and elsewhere) @@ -36,31 +37,20 @@ without express or implied warranty. */ -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -typedef struct _timer { - int heap_pos; - /* time for timer to go off, absolute time */ - long time; - /* procedure to call when timer goes off */ - void (*func)P((void*)); - /* argument for that procedure */ - void * arg; -} *timer; +typedef void (*timer_proc) __P((void *)); -#define NOW t_local.tv_sec -typedef void (*timer_proc) P((void *)); -extern timer timer_set_rel P((long, timer_proc, void*)); -extern timer timer_set_abs P((long, timer_proc, void*)); -extern void timer_reset P((timer)), timer_process P((void)); +typedef struct _Timer { + int heap_pos; /* Position in timer heap */ + long abstime; + timer_proc func; + void *arg; +} Timer; -#undef P +Timer *timer_set_rel __P((long, timer_proc, void *)); +Timer *timer_set_abs __P((long, timer_proc, void *)); +void timer_reset __P((Timer *)); +void timer_process __P((void)); +struct timeval *timer_timeout __P((struct timeval *tvbuf)); -#define timer_when(x) ALARM_TIME(x) +#endif /* __TIMER_H */ -extern struct timeval t_local; -extern long nexttimo; /* Unix time of next timout */ diff --git a/server/uloc.c b/server/uloc.c index 018d657..9bd7a11 100644 --- a/server/uloc.c +++ b/server/uloc.c @@ -12,16 +12,16 @@ */ #include <zephyr/mit-copyright.h> +#include "zserver.h" +#include <sys/socket.h> #ifndef lint #ifndef SABER -static char rcsid_uloc_c[] = - "$Id$"; +static const char rcsid_uloc_c[] = +"$Id$"; #endif /* SABER */ #endif /* lint */ -#include "zserver.h" - /* * The user locator functions. * @@ -31,13 +31,13 @@ static char rcsid_uloc_c[] = * ZNotice_t *notice; * int auth; * struct sockaddr_in *who; - * ZServerDesc_t *server; + * Server *server; * * void ulogin_dispatch(notice, auth, who, server) * ZNotice_t *notice; * int auth; * struct sockaddr_in *who; - * ZServerDesc_t *server; + * Server *server; * * void uloc_hflush(addr) * struct in_addr *addr; @@ -45,9 +45,7 @@ static char rcsid_uloc_c[] = * void uloc_flush_client(sin) * struct sockaddr_in *sin; * - * Code_t uloc_send_locations(host, version) - * ZHostList_t *host; - * char *version; + * Code_t uloc_send_locations() * * void uloc_dump_locs(fp) * FILE *fp; @@ -55,7 +53,7 @@ static char rcsid_uloc_c[] = /* * The user locator. - * We maintain an array of ZLocation_t sorted by user (so we can do + * We maintain an array of Location sorted by user (so we can do * binary searches), growing and shrinking it as necessary. */ @@ -64,58 +62,53 @@ static char rcsid_uloc_c[] = /* else you will lose. See ulogin_locate() and uloc_send_locations() */ #define NUM_FIELDS 3 -typedef enum _exposure_type { - NONE, - OPSTAFF_VIS, - REALM_VIS, - REALM_ANN, - NET_VIS, - NET_ANN -} exposure_type; - -typedef struct _ZLocation_t { - ZSTRING * zlt_user; - ZSTRING * zlt_machine; - char * zlt_time; /* in ctime format */ - ZSTRING * zlt_tty; - struct in_addr zlt_addr; /* IP addr of this loc */ - unsigned short zlt_port; /* port of registering client-- - for removing old entries */ - exposure_type zlt_exposure; -} ZLocation_t; - -#define NULLZLT ((ZLocation_t *) 0) +typedef enum _Exposure_type { + NONE, + OPSTAFF_VIS, + REALM_VIS, + REALM_ANN, + NET_VIS, + NET_ANN +} Exposure_type; + +typedef struct _Location { + String *user; + String *machine; + char *time; /* in ctime format */ + String *tty; + struct sockaddr_in addr; /* IP address and port of location */ + Exposure_type exposure; +} Location; + #define NOLOC 1 #define QUIET -1 #define UNAUTH -2 -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -static void ulogin_locate P((ZNotice_t *notice, struct sockaddr_in *who, - int auth)), - ulogin_flush_user P((ZNotice_t *notice)); -static ZLocation_t *ulogin_find P((ZNotice_t *notice, int strict)); -static int ulogin_setup P((ZNotice_t *notice, ZLocation_t *locs, - exposure_type exposure, struct sockaddr_in *who)), - ulogin_add_user P((ZNotice_t *notice, exposure_type exposure, - struct sockaddr_in *who)), - ulogin_parse P((ZNotice_t *notice, ZLocation_t *locs)), - ulogin_expose_user P((ZNotice_t *notice, exposure_type exposure)); -static exposure_type ulogin_remove_user P((ZNotice_t *notice, int auth, - struct sockaddr_in *who, - int *err_return)); -static void login_sendit P((ZNotice_t *notice, int auth, struct sockaddr_in *who)); -static char **ulogin_marshal_locs P((ZNotice_t *notice, int *found, int auth)); - -static int ul_equiv P((ZLocation_t *l1, ZLocation_t *l2)); - -static void free_loc P((ZLocation_t *loc)); - -static ZLocation_t *locations = NULLZLT; /* ptr to first in array */ +static void ulogin_locate __P((ZNotice_t *notice, struct sockaddr_in *who, + int auth)), +ulogin_flush_user __P((ZNotice_t *notice)); +static Location *ulogin_find __P((ZNotice_t *notice, int strict)); +static int ulogin_setup __P((ZNotice_t *notice, Location *locs, + Exposure_type exposure, struct sockaddr_in *who)), +ulogin_add_user __P((ZNotice_t *notice, Exposure_type exposure, + struct sockaddr_in *who)), +ulogin_parse __P((ZNotice_t *notice, Location *locs)), +ulogin_expose_user __P((ZNotice_t *notice, Exposure_type exposure)); +static Exposure_type ulogin_remove_user __P((ZNotice_t *notice, int auth, + struct sockaddr_in *who, + int *err_return)); +static void login_sendit __P((ZNotice_t *notice, int auth, + struct sockaddr_in *who, int external)); +static char **ulogin_marshal_locs __P((ZNotice_t *notice, int *found, + int auth)); + +static int ul_equiv __P((Location *l1, Location *l2)); + +static void free_loc __P((Location *loc)); +static void ulogin_locate_forward __P((ZNotice_t *notice, + struct sockaddr_in *who, Realm *realm)); + +static Location *locations = NULL; /* ptr to first in array */ static int num_locs = 0; /* number in array */ /* @@ -124,197 +117,199 @@ static int num_locs = 0; /* number in array */ Code_t ulogin_dispatch(notice, auth, who, server) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - ZServerDesc_t *server; + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + Server *server; { - exposure_type retval; - int err_ret; - ZHostList_t *host; + Exposure_type retval; + int err_ret; #if 0 - zdbug((LOG_DEBUG, - "ulogin_dispatch: opc=%s from=%s/%d auth=%d who=%s/%d", - notice->z_opcode, notice->z_sender, ntohs (notice->z_port), - auth, inet_ntoa (who->sin_addr), ntohs (who->sin_port))); + zdbug((LOG_DEBUG, + "ulogin_dispatch: opc=%s from=%s/%d auth=%d who=%s/%d", + notice->z_opcode, notice->z_sender, ntohs (notice->z_port), + auth, inet_ntoa (who->sin_addr), ntohs (who->sin_port))); #endif - host = hostm_find_host(&who->sin_addr); - if (host && host->zh_locked) - return(ZSRV_REQUEUE); - - if (!strcmp(notice->z_opcode, LOGIN_USER_LOGOUT)) { + if (strcmp(notice->z_opcode, LOGIN_USER_LOGOUT) == 0) { #if 0 - zdbug((LOG_DEBUG,"logout")); + zdbug((LOG_DEBUG,"logout")); #endif - retval = ulogin_remove_user(notice, auth, who, &err_ret); - switch (retval) { - case NONE: - if (err_ret == UNAUTH) { + retval = ulogin_remove_user(notice, auth, who, &err_ret); + switch (retval) { + case NONE: + if (err_ret == UNAUTH) { #if 0 - zdbug((LOG_DEBUG, "unauth logout: %s %d", - inet_ntoa(who->sin_addr), - ntohs(notice->z_port))); + zdbug((LOG_DEBUG, "unauth logout: %s %d", + inet_ntoa(who->sin_addr), + ntohs(notice->z_port))); #endif - if (server == me_server) - clt_ack(notice, who, AUTH_FAILED); - return(ZERR_NONE); - } else if (err_ret == NOLOC) { - if (server == me_server) - clt_ack(notice, who, NOT_FOUND); - return(ZERR_NONE); - } - syslog(LOG_ERR,"bogus location exposure NONE, %s", - notice->z_sender); - break; - case OPSTAFF_VIS: - case REALM_VIS: - /* he is not announced to people. Silently ack */ - if (server == me_server) - ack(notice, who); - break; - case REALM_ANN: - case NET_VIS: - case NET_ANN: - /* currently no distinction between these. - just announce */ - /* we assume that if this user is at a certain - IP address, we can trust the logout to be - authentic. ulogin_remove_user checks the - ip addrs */ - if (server == me_server) - sendit(notice, 1, who); - break; - default: - syslog(LOG_ERR,"bogus location exposure %d/%s", - (int) retval, notice->z_sender); - break; - } - if (server == me_server) /* tell the other servers */ - server_forward(notice, auth, who); - return(ZERR_NONE); + if (server == me_server) + clt_ack(notice, who, AUTH_FAILED); + return ZERR_NONE; + } else if (err_ret == NOLOC) { + if (server == me_server) + clt_ack(notice, who, NOT_FOUND); + return ZERR_NONE; + } + syslog(LOG_ERR,"bogus location exposure NONE, %s", + notice->z_sender); + break; + case OPSTAFF_VIS: + case REALM_VIS: + /* he is not announced to people. Silently ack */ + if (server == me_server) + ack(notice, who); + break; + case REALM_ANN: + case NET_VIS: + if (server == me_server) + sendit(notice, 1, who, 0); + break; + case NET_ANN: + /* currently no distinction between these. + just announce */ + /* we assume that if this user is at a certain + IP address, we can trust the logout to be + authentic. ulogin_remove_user checks the + ip addrs */ + if (server == me_server) + sendit(notice, 1, who, 1); + break; + default: + syslog(LOG_ERR,"bogus location exposure %d/%s", + (int) retval, notice->z_sender); + break; } - if (!bdumping && - (!auth || strcmp(notice->z_sender, notice->z_class_inst))) { + if (server == me_server) /* tell the other servers */ + server_forward(notice, auth, who); + return ZERR_NONE; + } + if (!bdumping && + (!auth || strcmp(notice->z_sender, notice->z_class_inst) != 0)) { #if 1 - zdbug((LOG_DEBUG,"unauthentic ulogin: %d %s %s", auth, - notice->z_sender, notice->z_class_inst)); + zdbug((LOG_DEBUG,"unauthentic ulogin: %d %s %s", auth, + notice->z_sender, notice->z_class_inst)); #endif - if (server == me_server) - clt_ack(notice, who, AUTH_FAILED); - return(ZERR_NONE); - } - if (!strcmp(notice->z_opcode, LOGIN_USER_FLUSH)) { + if (server == me_server) + clt_ack(notice, who, AUTH_FAILED); + return ZERR_NONE; + } + if (strcmp(notice->z_opcode, LOGIN_USER_FLUSH) == 0) { #if 0 - zdbug((LOG_DEBUG, "user flush")); + zdbug((LOG_DEBUG, "user flush")); #endif - ulogin_flush_user(notice); - if (server == me_server) - ack(notice, who); - } else if (!strcmp(notice->z_opcode, EXPOSE_NONE)) { + ulogin_flush_user(notice); + if (server == me_server) + ack(notice, who); + } else if (strcmp(notice->z_opcode, EXPOSE_NONE) == 0) { #if 0 - zdbug((LOG_DEBUG,"no expose")); + zdbug((LOG_DEBUG,"no expose")); #endif - (void) ulogin_remove_user(notice, auth, who, &err_ret); - if (err_ret == UNAUTH) { + ulogin_remove_user(notice, auth, who, &err_ret); + if (err_ret == UNAUTH) { #if 0 - zdbug((LOG_DEBUG, "unauth noexpose: %s/%d", - inet_ntoa(who->sin_addr), - ntohs(notice->z_port))); + zdbug((LOG_DEBUG, "unauth noexpose: %s/%d", + inet_ntoa(who->sin_addr), ntohs(notice->z_port))); #endif - if (server == me_server) - clt_ack(notice, who, AUTH_FAILED); - return(ZERR_NONE); - } else if (err_ret == NOLOC) { - if (server == me_server) - clt_ack(notice, who, NOT_FOUND); - return(ZERR_NONE); - } - if (server == me_server) { - ack(notice, who); - server_forward(notice, auth, who); - } - return(ZERR_NONE); - } else if (!strcmp(notice->z_opcode, EXPOSE_OPSTAFF)) { + if (server == me_server) + clt_ack(notice, who, AUTH_FAILED); + return ZERR_NONE; + } else if (err_ret == NOLOC) { + if (server == me_server) + clt_ack(notice, who, NOT_FOUND); + return ZERR_NONE; + } + if (server == me_server) { + ack(notice, who); + server_forward(notice, auth, who); + } + return ZERR_NONE; + } else if (strcmp(notice->z_opcode, EXPOSE_OPSTAFF) == 0) { #if 0 - zdbug((LOG_DEBUG,"opstaff")); + zdbug((LOG_DEBUG,"opstaff")); #endif - err_ret = ulogin_add_user(notice, OPSTAFF_VIS, who); - if (server == me_server) - if (err_ret) - nack(notice, who); - else - ack(notice, who); - } else if (!strcmp(notice->z_opcode, EXPOSE_REALMVIS)) { + err_ret = ulogin_add_user(notice, OPSTAFF_VIS, who); + if (server == me_server) { + if (err_ret) + nack(notice, who); + else + ack(notice, who); + } + } else if (strcmp(notice->z_opcode, EXPOSE_REALMVIS) == 0) { #if 0 - zdbug((LOG_DEBUG,"realmvis")); + zdbug((LOG_DEBUG,"realmvis")); #endif - err_ret = ulogin_add_user(notice, REALM_VIS, who); - if (server == me_server) /* realm vis is not broadcast, - so we ack it here */ - if (err_ret) - nack(notice, who); - else - ack(notice, who); - } else if (!strcmp(notice->z_opcode, EXPOSE_REALMANN)) { + err_ret = ulogin_add_user(notice, REALM_VIS, who); + if (server == me_server) { /* realm vis is not broadcast, + so we ack it here */ + if (err_ret) + nack(notice, who); + else + ack(notice, who); + } + } else if (!strcmp(notice->z_opcode, EXPOSE_REALMANN)) { #if 0 - zdbug((LOG_DEBUG,"realmann")); + zdbug((LOG_DEBUG,"realmann")); #endif - err_ret = ulogin_add_user(notice, REALM_ANN, who); - if (server == me_server) /* announce to the realm */ - if (err_ret) - nack(notice, who); - else - login_sendit(notice, auth, who); - } else if (!strcmp(notice->z_opcode, EXPOSE_NETVIS)) { + err_ret = ulogin_add_user(notice, REALM_ANN, who); + if (server == me_server) { /* announce to the realm */ + if (err_ret) + nack(notice, who); + else + login_sendit(notice, auth, who, 0); + } + } else if (!strcmp(notice->z_opcode, EXPOSE_NETVIS)) { #if 0 - zdbug((LOG_DEBUG,"netvis")); + zdbug((LOG_DEBUG,"netvis")); #endif - err_ret = ulogin_add_user(notice, NET_VIS, who); - if (server == me_server) /* announce to the realm */ - if (err_ret) - nack(notice, who); - else - login_sendit(notice, auth, who); - } else if (!strcmp(notice->z_opcode, EXPOSE_NETANN)) { + err_ret = ulogin_add_user(notice, NET_VIS, who); + if (server == me_server) { /* announce to the realm */ + if (err_ret) + nack(notice, who); + else + login_sendit(notice, auth, who, 0); + } + } else if (!strcmp(notice->z_opcode, EXPOSE_NETANN)) { #if 0 - zdbug((LOG_DEBUG,"netann")); + zdbug((LOG_DEBUG,"netann")); #endif - err_ret = ulogin_add_user(notice, NET_ANN, who); - if (server == me_server) /* tell the world */ - if (err_ret) - nack(notice, who); - else - login_sendit(notice, auth, who); - } else { - syslog(LOG_ERR, "unknown ulog opcode %s", notice->z_opcode); - if (server == me_server) - nack(notice, who); - return(ZERR_NONE); + err_ret = ulogin_add_user(notice, NET_ANN, who); + if (server == me_server) { /* tell the world */ + if (err_ret) + nack(notice, who); + else + login_sendit(notice, auth, who, 1); } + } else { + syslog(LOG_ERR, "unknown ulog opcode %s", notice->z_opcode); if (server == me_server) - server_forward(notice, auth, who); - return(ZERR_NONE); + nack(notice, who); + return ZERR_NONE; + } + if (server == me_server) + server_forward(notice, auth, who); + return ZERR_NONE; } static void -login_sendit(notice, auth, who) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; +login_sendit(notice, auth, who, external) + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + int external; { - ZNotice_t log_notice; + ZNotice_t log_notice; - /* we must copy the notice struct here because we need the original - for forwarding. We needn't copy the private data of the notice, - since that isn't modified by sendit and its subroutines. */ + /* we must copy the notice struct here because we need the original + for forwarding. We needn't copy the private data of the notice, + since that isn't modified by sendit and its subroutines. */ - log_notice = *notice; + log_notice = *notice; - log_notice.z_opcode = LOGIN_USER_LOGIN; - sendit(&log_notice, auth, who); - return; + log_notice.z_opcode = LOGIN_USER_LOGIN; + sendit(&log_notice, auth, who, external); } @@ -323,46 +318,53 @@ login_sendit(notice, auth, who) */ Code_t ulocate_dispatch(notice, auth, who, server) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - ZServerDesc_t *server; + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + Server *server; { + char *cp; + Realm *realm; + #if 0 - zdbug((LOG_DEBUG,"ulocate_disp")); + zdbug((LOG_DEBUG,"ulocate_disp")); #endif -#if 0 /* Now we support unauthentic locate for net-visible. */ - if (!auth) { +#if 0 /* Now we support unauthentic locate for net-visible. */ + if (!auth) { #if 0 - zdbug((LOG_DEBUG,"unauthentic ulocate")); + zdbug((LOG_DEBUG,"unauthentic ulocate")); #endif - if (server == me_server) - clt_ack(notice, who, AUTH_FAILED); - return(ZERR_NONE); - } + if (server == me_server) + clt_ack(notice, who, AUTH_FAILED); + return ZERR_NONE; + } #endif - if (!strcmp(notice->z_opcode, LOCATE_LOCATE)) { + if (!strcmp(notice->z_opcode, LOCATE_LOCATE)) { #if 0 - zdbug((LOG_DEBUG,"locate")); + zdbug((LOG_DEBUG,"locate")); #endif - /* we are talking to a current-rev client; send an ack */ - ack(notice, who); - ulogin_locate(notice, who, auth); - return(ZERR_NONE); - } else { - syslog(LOG_ERR, "unknown uloc opcode %s", notice->z_opcode); - if (server == me_server) - nack(notice, who); - return(ZERR_NONE); - } + /* we are talking to a current-rev client; send an ack */ + ack(notice, who); + cp = strchr(notice->z_class_inst, '@'); + if (cp && (realm = realm_get_realm_by_name(cp + 1))) + ulogin_locate_forward(notice, who, realm); + else + ulogin_locate(notice, who, auth); + return ZERR_NONE; + } else { + syslog(LOG_ERR, "unknown uloc opcode %s", notice->z_opcode); + if (server == me_server) + nack(notice, who); + return ZERR_NONE; + } #if 0 - if (server == me_server) { - server_forward(notice, auth, who); - ack(notice, who); - } + if (server == me_server) { + server_forward(notice, auth, who); + ack(notice, who); + } + return ZERR_NONE; #endif - return(ZERR_NONE); } /* @@ -371,135 +373,121 @@ ulocate_dispatch(notice, auth, who, server) void uloc_hflush(addr) - struct in_addr *addr; + struct in_addr *addr; { - ZLocation_t *loc; - register int i = 0, new_num = 0; - - if (num_locs == 0) - return; /* none to flush */ - - START_CRITICAL_CODE; - - /* slightly inefficient, assume the worst, and allocate enough space */ - loc = (ZLocation_t *) xmalloc(num_locs *sizeof(ZLocation_t)); - if (!loc) { - syslog(LOG_CRIT, "uloc_flush alloc"); - abort(); - /*NOTREACHED*/ - } - - /* copy entries which don't match */ - while (i < num_locs) { - if (locations[i].zlt_addr.s_addr != addr->s_addr) - loc[new_num++] = locations[i]; - else { + Location *loc; + int i = 0, new_num = 0; + + if (num_locs == 0) + return; /* none to flush */ + + /* slightly inefficient, assume the worst, and allocate enough space */ + loc = (Location *) malloc(num_locs *sizeof(Location)); + if (!loc) { + syslog(LOG_CRIT, "uloc_flush alloc"); + abort(); + } + + /* copy entries which don't match */ + while (i < num_locs) { + if (locations[i].addr.sin_addr.s_addr != addr->s_addr) { + loc[new_num++] = locations[i]; + } else { #if 0 - if (zdebug) - syslog(LOG_DEBUG, "uloc hflushing %s/%s/%s", - locations[i].zlt_user->string, - locations[i].zlt_machine->string, - locations[i].zlt_tty->string); + if (zdebug) + syslog(LOG_DEBUG, "uloc hflushing %s/%s/%s", + locations[i].user->string, + locations[i].machine->string, + locations[i].tty->string); #endif - free_loc(&locations[i]); - } - i++; + free_loc(&locations[i]); } + i++; + } - xfree(locations); - locations = NULLZLT; + free(locations); + locations = NULL; - if (!new_num) { + if (!new_num) { #if 0 - zdbug((LOG_DEBUG,"no more locs")); + zdbug((LOG_DEBUG,"no more locs")); #endif - xfree(loc); - loc = NULLZLT; - num_locs = new_num; - - END_CRITICAL_CODE; - - return; - } - locations = loc; + free(loc); + loc = NULL; num_locs = new_num; - END_CRITICAL_CODE; - - /* all done */ return; + } + locations = loc; + num_locs = new_num; + + /* all done */ + return; } void uloc_flush_client(sin) - struct sockaddr_in *sin; + struct sockaddr_in *sin; { - ZLocation_t *loc; - register int i = 0, new_num = 0; - - if (num_locs == 0) - return; /* none to flush */ - - START_CRITICAL_CODE; - - /* slightly inefficient, assume the worst, and allocate enough space */ - loc = (ZLocation_t *) xmalloc(num_locs *sizeof(ZLocation_t)); - if (!loc) { - syslog(LOG_CRIT, "uloc_flush_clt alloc"); - abort(); - /*NOTREACHED*/ - } - - /* copy entries which don't match */ - while (i < num_locs) { - if ((locations[i].zlt_addr.s_addr != sin->sin_addr.s_addr) - || (locations[i].zlt_port != sin->sin_port)) - loc[new_num++] = locations[i]; - else { + Location *loc; + int i = 0, new_num = 0; + + if (num_locs == 0) + return; /* none to flush */ + + /* slightly inefficient, assume the worst, and allocate enough space */ + loc = (Location *) malloc(num_locs *sizeof(Location)); + if (!loc) { + syslog(LOG_CRIT, "uloc_flush_clt alloc"); + abort(); + } + + /* copy entries which don't match */ + while (i < num_locs) { + if ((locations[i].addr.sin_addr.s_addr != sin->sin_addr.s_addr) + || (locations[i].addr.sin_port != sin->sin_port)) { + loc[new_num++] = locations[i]; + } else { #if 0 - if (zdebug) - syslog(LOG_DEBUG, "uloc cflushing %s/%s/%s", - locations[i].zlt_user->string, - locations[i].zlt_machine->string, - locations[i].zlt_tty->string); + if (zdebug) + syslog(LOG_DEBUG, "uloc cflushing %s/%s/%s", + locations[i].user->string, + locations[i].machine->string, + locations[i].tty->string); #endif - free_loc(&locations[i]); - } - i++; + free_loc(&locations[i]); } + i++; + } - xfree(locations); - locations = NULLZLT; + free(locations); + locations = NULL; - if (!new_num) { + if (!new_num) { #if 0 - zdbug((LOG_DEBUG,"no more locs")); + zdbug((LOG_DEBUG,"no more locs")); #endif - xfree(loc); - loc = NULLZLT; - num_locs = new_num; - - END_CRITICAL_CODE; - - return; - } - locations = loc; + free(loc); + loc = NULL; num_locs = new_num; - END_CRITICAL_CODE; + return; + } + locations = loc; + num_locs = new_num; #ifdef DEBUG - if (zdebug) { - register int i; + if (zdebug) { + int i; - for (i = 0; i < num_locs; i++) - syslog(LOG_DEBUG, "%s/%d", - locations[i].zlt_user->string, - (int) locations[i].zlt_exposure); + for (i = 0; i < num_locs; i++) { + syslog(LOG_DEBUG, "%s/%d", locations[i].user->string, + (int) locations[i].exposure); } + } #endif - /* all done */ - return; + /* all done */ + return; } /* @@ -508,59 +496,49 @@ uloc_flush_client(sin) /*ARGSUSED*/ Code_t -uloc_send_locations(host, vers) - ZHostList_t *host; - char *vers; +uloc_send_locations() { - register ZLocation_t *loc; - register int i; - register struct in_addr *haddr = &host->zh_addr.sin_addr; - char *lyst[NUM_FIELDS]; - char *exposure_level; - Code_t retval; - - for (i = 0, loc = locations; i < num_locs; i++, loc++) { - if (loc->zlt_addr.s_addr != haddr->s_addr) - continue; - lyst[0] = (char *) loc->zlt_machine->string; - lyst[1] = (char *) loc->zlt_time; - lyst[2] = (char *) loc->zlt_tty->string; - - switch (loc->zlt_exposure) { - case OPSTAFF_VIS: - exposure_level = EXPOSE_OPSTAFF; - break; - case REALM_VIS: - exposure_level = EXPOSE_REALMVIS; - break; - case REALM_ANN: - exposure_level = EXPOSE_REALMANN; - break; - case NET_VIS: - exposure_level = EXPOSE_NETVIS; - break; - case NET_ANN: - exposure_level = EXPOSE_NETANN; - break; - default: - syslog(LOG_ERR,"broken location state %s/%d", - loc->zlt_user->string, - (int) loc->zlt_exposure); - break; - } - retval = bdump_send_list_tcp(ACKED, loc->zlt_port, - LOGIN_CLASS, - (char *) loc->zlt_user->string, /* XXX */ - exposure_level, - myname, "", lyst, - NUM_FIELDS); - if (retval != ZERR_NONE) { - syslog(LOG_ERR, "uloc_send_locs: %s", - error_message(retval)); - return(retval); - } + Location *loc; + int i; + char *lyst[NUM_FIELDS]; + char *exposure_level; + Code_t retval; + + for (i = 0, loc = locations; i < num_locs; i++, loc++) { + lyst[0] = (char *) loc->machine->string; + lyst[1] = (char *) loc->time; + lyst[2] = (char *) loc->tty->string; + + switch (loc->exposure) { + case OPSTAFF_VIS: + exposure_level = EXPOSE_OPSTAFF; + break; + case REALM_VIS: + exposure_level = EXPOSE_REALMVIS; + break; + case REALM_ANN: + exposure_level = EXPOSE_REALMANN; + break; + case NET_VIS: + exposure_level = EXPOSE_NETVIS; + break; + case NET_ANN: + exposure_level = EXPOSE_NETANN; + break; + default: + syslog(LOG_ERR,"broken location state %s/%d", + loc->user->string, (int) loc->exposure); + break; + } + retval = bdump_send_list_tcp(ACKED, &loc->addr, LOGIN_CLASS, + loc->user->string, exposure_level, myname, + "", lyst, NUM_FIELDS); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "uloc_send_locs: %s", error_message(retval)); + return(retval); } - return(ZERR_NONE); + } + return ZERR_NONE; } /* @@ -569,88 +547,81 @@ uloc_send_locations(host, vers) static int ulogin_add_user(notice, exposure, who) - ZNotice_t *notice; - exposure_type exposure; - struct sockaddr_in *who; + ZNotice_t *notice; + Exposure_type exposure; + struct sockaddr_in *who; { - ZLocation_t *oldlocs, newloc; - register int i; + Location *oldlocs, newloc; + int i; - if ((oldlocs = ulogin_find(notice,1)) != NULLZLT) { + if ((oldlocs = ulogin_find(notice,1)) != NULL) { #if 0 - zdbug((LOG_DEBUG,"ul_add: already here")); + zdbug((LOG_DEBUG,"ul_add: already here")); #endif - (void) ulogin_expose_user(notice, exposure); - return 0; - } - - oldlocs = locations; - - START_CRITICAL_CODE; - - locations = (ZLocation_t *) xmalloc((num_locs +1) * - sizeof(ZLocation_t)); - if (!locations) { - syslog(LOG_ERR, "zloc mem alloc"); - locations = oldlocs; - return 1; - } - - if (num_locs == 0) { /* first one */ - if (ulogin_setup(notice, locations, exposure, who)) { - xfree(locations); - locations = NULLZLT; - END_CRITICAL_CODE; - return 1; - } - num_locs = 1; - goto dprnt; - } - - /* not the first one, insert him */ - - if (ulogin_setup(notice, &newloc, exposure, who)) { - xfree(locations); - locations = oldlocs; - END_CRITICAL_CODE; - return 1; - } - num_locs++; + ulogin_expose_user(notice, exposure); + return 0; + } - /* copy old locs */ - i = 0; - while ((i < num_locs-1) && - (comp_zstring(oldlocs[i].zlt_user,newloc.zlt_user) < 0)) { - locations[i] = oldlocs[i]; - i++; - } + oldlocs = locations; - /* add him in here */ - locations[i++] = newloc; + locations = (Location *) malloc((num_locs + 1) * sizeof(Location)); + if (!locations) { + syslog(LOG_ERR, "zloc mem alloc"); + locations = oldlocs; + return 1; + } - /* copy the rest */ - while (i < num_locs) { - locations[i] = oldlocs[i - 1]; - i++; + if (num_locs == 0) { /* first one */ + if (ulogin_setup(notice, locations, exposure, who)) { + free(locations); + locations = NULL; + return 1; } - if (oldlocs) - xfree(oldlocs); - - dprnt: + num_locs = 1; + goto dprnt; + } + + /* not the first one, insert him */ + + if (ulogin_setup(notice, &newloc, exposure, who)) { + free(locations); + locations = oldlocs; + return 1; + } + num_locs++; + + /* copy old locs */ + i = 0; + while ((i < num_locs-1) && + (comp_string(oldlocs[i].user,newloc.user) < 0)) { + locations[i] = oldlocs[i]; + i++; + } + + /* add him in here */ + locations[i++] = newloc; + + /* copy the rest */ + while (i < num_locs) { + locations[i] = oldlocs[i - 1]; + i++; + } + if (oldlocs) + free(oldlocs); + + dprnt: #if 0 - if (zdebug) { - register int i; - syslog(LOG_DEBUG, "ul_add: New Locations (%d)", num_locs); - for (i = 0; i < num_locs; i++) - syslog(LOG_DEBUG, "%s/%s/%s/%d", - locations[i].zlt_user->string, - locations[i].zlt_machine->string, - locations[i].zlt_tty->string, - (int) locations[i].zlt_exposure); + if (zdebug) { + int i; + syslog(LOG_DEBUG, "ul_add: New Locations (%d)", num_locs); + for (i = 0; i < num_locs; i++) { + syslog(LOG_DEBUG, "%s/%s/%s/%d", locations[i].user->string, + locations[i].machine->string, locations[i].tty->string, + (int) locations[i].exposure); } + } #endif - END_CRITICAL_CODE; - return 0; + return 0; } /* @@ -659,41 +630,19 @@ ulogin_add_user(notice, exposure, who) static int ulogin_setup(notice, locs, exposure, who) - ZNotice_t *notice; - ZLocation_t *locs; - exposure_type exposure; - struct sockaddr_in *who; + ZNotice_t *notice; + Location *locs; + Exposure_type exposure; + struct sockaddr_in *who; { - if (ulogin_parse(notice, locs)) - return(1); - - if (!locs->zlt_user) { - syslog(LOG_ERR, "zloc bad format: no user"); - return(1); - } - if (!locs->zlt_machine) { - syslog(LOG_ERR, "zloc bad format: no machine"); - free_zstring(locs->zlt_user); - return(1); - - } - if (!locs->zlt_tty) { - syslog(LOG_ERR, "zloc bad format: no tty"); - free_zstring(locs->zlt_user); - free_zstring(locs->zlt_machine); - return(1); - } - if (!locs->zlt_time) { - syslog(LOG_ERR, "zloc bad format: no time"); - free_zstring(locs->zlt_user); - free_zstring(locs->zlt_machine); - free_zstring(locs->zlt_tty); - return(1); - } - locs->zlt_exposure = exposure; - locs->zlt_addr = who->sin_addr; - locs->zlt_port = notice->z_port; - return(0); + if (ulogin_parse(notice, locs)) + return 1; + + locs->exposure = exposure; + locs->addr.sin_family = AF_INET; + locs->addr.sin_addr.s_addr = who->sin_addr.s_addr; + locs->addr.sin_port = notice->z_port; + return(0); } /* @@ -702,56 +651,50 @@ ulogin_setup(notice, locs, exposure, who) static int ulogin_parse(notice, locs) - ZNotice_t *notice; - ZLocation_t *locs; + ZNotice_t *notice; + Location *locs; { - register char *cp, *base; - register int nulls = 0; - - if (!notice->z_message_len) { - syslog(LOG_ERR, "short ulogin"); - return(1); - } - - base = notice->z_message; - for (cp = base; cp < base + notice->z_message_len; cp++) - if (! *cp) nulls++; - if (nulls < 3) { - syslog(LOG_ERR, "zloc bad format from user %s (only %d fields)", - notice->z_sender, nulls); - return 1; - } - - locs->zlt_user = make_zstring(notice->z_class_inst,0); - - cp = base; - locs->zlt_machine = make_zstring(cp,0); + char *cp, *base; + int nulls = 0; + + if (!notice->z_message_len) { + syslog(LOG_ERR, "short ulogin"); + return 1; + } + + base = notice->z_message; + for (cp = base; cp < base + notice->z_message_len; cp++) { + if (!*cp) + nulls++; + } + if (nulls < 3) { + syslog(LOG_ERR, "zloc bad format from user %s (only %d fields)", + notice->z_sender, nulls); + return 1; + } + + locs->user = make_string(notice->z_class_inst,0); + + cp = base; + locs->machine = make_string(cp,0); #if 0 - zdbug((LOG_DEBUG, "ul_parse: mach %s", cp)); + zdbug((LOG_DEBUG, "ul_parse: mach %s", cp)); #endif - cp += (strlen(cp) + 1); - locs->zlt_time = strsave(cp); + cp += (strlen(cp) + 1); + locs->time = strsave(cp); #if 0 - zdbug((LOG_DEBUG, "ul_parse: time %s", cp)); + zdbug((LOG_DEBUG, "ul_parse: time %s", cp)); #endif - /* This field might not be null-terminated */ - cp += (strlen(cp) + 1); -#if 0 - if (nulls == 2) { - s = (char *)xmalloc(base + notice->z_message_len - cp + 1); - strncpy(s, cp); - locs->zlt_tty = make_zstring(s, 0); - xfree(s); - } else -#endif - locs->zlt_tty = make_zstring(cp,0); + /* This field might not be null-terminated */ + cp += (strlen(cp) + 1); + locs->tty = make_string(cp, 0); #if 0 - zdbug((LOG_DEBUG, "ul_parse: tty %s", locs->zlt_tty->string)); + zdbug((LOG_DEBUG, "ul_parse: tty %s", locs->tty->string)); #endif - return 0; + return 0; } /* @@ -761,190 +704,178 @@ ulogin_parse(notice, locs) * in the table. */ -static ZLocation_t * +static Location * ulogin_find(notice, strict) - ZNotice_t *notice; - int strict; + ZNotice_t *notice; + int strict; { - register int i, rlo, rhi; - ZLocation_t tmploc; - int compar; - ZSTRING *inst; + int i, rlo, rhi; + Location tmploc; + int compar; + String *inst; - if (!locations) - return(NULLZLT); + if (!locations) + return(NULL); - inst = make_zstring(notice->z_class_inst,0); + inst = make_string(notice->z_class_inst, 0); - /* i is the current loc we are checking */ - /* rlo is the lowest we will still check, rhi is the highest we will - still check */ + /* i is the current loc we are checking */ + /* rlo is the lowest we will still check, rhi is the highest we will + still check */ - i = num_locs >> 1; /* start in the middle */ - rlo = 0; - rhi = num_locs - 1; /* first index is 0 */ + i = num_locs >> 1; /* start in the middle */ + rlo = 0; + rhi = num_locs - 1; /* first index is 0 */ - while ((compar = comp_zstring(locations[i].zlt_user, inst)) != 0) { + while ((compar = comp_string(locations[i].user, inst)) != 0) { #if 0 - zdbug ((LOG_DEBUG, "ulogin_find: comparing %s %s %s %d %d", - notice->z_class_inst, - locations[i].zlt_user->string, - locations[i].zlt_tty->string, - rlo, rhi)); + zdbug ((LOG_DEBUG, "ulogin_find: comparing %s %s %s %d %d", + notice->z_class_inst, locations[i].user->string, + locations[i].tty->string, rlo, rhi)); #endif - if (compar < 0) - rlo = i + 1; - else - rhi = i - 1; - if (rhi - rlo < 0) { + if (compar < 0) + rlo = i + 1; + else + rhi = i - 1; + if (rhi - rlo < 0) { #if 0 - zdbug((LOG_DEBUG,"ul_find: %s not found", - inst->string)); + zdbug((LOG_DEBUG,"ul_find: %s not found", + inst->string)); #endif - free_zstring(inst); - return 0; - } - i = (rhi + rlo) >> 1; /* split the diff */ + free_string(inst); + return 0; } + i = (rhi + rlo) >> 1; /* split the diff */ + } #if 0 - zdbug((LOG_DEBUG, "ul_find: %s found at loc %d", - inst->string, i)); + zdbug((LOG_DEBUG, "ul_find: %s found at loc %d", + inst->string, i)); #endif - if (strict && ulogin_parse(notice, &tmploc)) { + if (strict && ulogin_parse(notice, &tmploc)) { #if 1 - zdbug((LOG_DEBUG,"ul_find bad fmt")); + zdbug((LOG_DEBUG,"ul_find bad fmt")); #endif - free_zstring(inst); - return 0; - } - /* back up to the first of this guy */ - while (i > 0 && (locations[i-1].zlt_user == inst)) { - i--; + free_string(inst); + return 0; + } + /* back up to the first of this guy */ + while (i > 0 && (locations[i-1].user == inst)) { + i--; #if 0 - zdbug ((LOG_DEBUG, - "ulogin_find: backing up: %s %d %s %s", - inst->string, i, - locations[i].zlt_user->string, - locations[i].zlt_tty->string)); + zdbug((LOG_DEBUG, "ulogin_find: backing up: %s %d %s %s", inst->string, + i, locations[i].user->string, locations[i].tty->string)); #endif - } - if (strict) - while (i < num_locs - && !ul_equiv(&tmploc, &locations[i]) - && (locations[i].zlt_user == inst)) { - i++; - } - - if ((i == num_locs) || (locations[i].zlt_user != inst)) { + } + if (strict) { + while (i < num_locs && !ul_equiv(&tmploc, &locations[i]) + && (locations[i].user == inst)) + i++; + } + if (strict) + free_loc(&tmploc); + if (i == num_locs || locations[i].user != inst) { #if 1 - zdbug((LOG_DEBUG,"ul_find final match loss")); + zdbug((LOG_DEBUG,"ul_find final match loss")); #endif - free_zstring(inst); - return 0; - } - if (strict) - free_loc(&tmploc); - free_zstring(inst); - return &locations[i]; + free_string(inst); + return 0; + } + free_string(inst); + return &locations[i]; } static int ul_equiv(l1, l2) -register ZLocation_t *l1, *l2; + Location *l1, *l2; { - if (l1->zlt_machine != l2->zlt_machine) - return(0); - if (l1->zlt_tty != l2->zlt_tty) - return(0); - return(1); + if (l1->machine != l2->machine) + return 0; + if (l1->tty != l2->tty) + return 0; + return 1; } /* * remove the user specified in notice from the internal table */ -static exposure_type +static Exposure_type ulogin_remove_user(notice, auth, who, err_return) - ZNotice_t *notice; - int auth; - struct sockaddr_in *who; - int *err_return; + ZNotice_t *notice; + int auth; + struct sockaddr_in *who; + int *err_return; { - ZLocation_t *loc, *loc2; - register int i = 0; - exposure_type quiet; + Location *new_locs, *loc; + int i = 0; + Exposure_type quiet; - *err_return = 0; - if (!(loc2 = ulogin_find(notice, 1))) { + *err_return = 0; + loc = ulogin_find(notice, 1); + if (!loc) { #if 0 - zdbug((LOG_DEBUG,"ul_rem: not here")); + zdbug((LOG_DEBUG,"ul_rem: not here")); #endif - *err_return = NOLOC; - return(NONE); - } + *err_return = NOLOC; + return NONE; + } - /* if unauthentic, the sender MUST be the same IP addr - that registered */ - if (!auth && loc2->zlt_addr.s_addr != who->sin_addr.s_addr) { - *err_return = UNAUTH; - return NONE; - } + /* if unauthentic, the sender MUST be the same IP addr that registered */ + if (!auth && loc->addr.sin_addr.s_addr != who->sin_addr.s_addr) { + *err_return = UNAUTH; + return NONE; + } - quiet = loc2->zlt_exposure; + quiet = loc->exposure; - START_CRITICAL_CODE; - if (--num_locs == 0) { /* last one */ + if (--num_locs == 0) { /* last one */ #if 0 - zdbug((LOG_DEBUG,"last loc")); + zdbug((LOG_DEBUG,"last loc")); #endif - free_loc(locations); - xfree(locations); - locations = NULLZLT; - END_CRITICAL_CODE; - return(quiet); - } - - loc = (ZLocation_t *) xmalloc(num_locs * sizeof(ZLocation_t)); - if (!loc) { - syslog(LOG_CRIT, "ul_rem alloc"); - abort(); - /*NOTREACHED*/ - } - - /* copy old entries */ - while (i < num_locs && &locations[i] < loc2) { - loc[i] = locations[i]; - i++; - } - - /* free up this one */ - free_loc(&locations[i]); - i++; /* skip over this one */ - - /* copy the rest */ - while (i <= num_locs) { - loc[i - 1] = locations[i]; - i++; - } - - xfree(locations); - - locations = loc; - - END_CRITICAL_CODE; + free_loc(locations); + free(locations); + locations = NULL; + return quiet; + } + + new_locs = (Location *) malloc(num_locs * sizeof(Location)); + if (!new_locs) { + syslog(LOG_CRIT, "ul_rem alloc"); + abort(); + } + + /* copy old entries */ + while (i < num_locs && &locations[i] < loc) { + new_locs[i] = locations[i]; + i++; + } + + /* free up this one */ + free_loc(&locations[i]); + i++; /* skip over this one */ + + /* copy the rest */ + while (i <= num_locs) { + new_locs[i - 1] = locations[i]; + i++; + } + + free(locations); + + locations = new_locs; #if defined(DEBUG) && 0 - if (zdebug) { - register int i; + if (zdebug) { + int i; - for (i = 0; i < num_locs; i++) - syslog(LOG_DEBUG, "%s/%d", - locations[i].zlt_user->string, - (int) locations[i].zlt_exposure); + for (i = 0; i < num_locs; i++) { + syslog(LOG_DEBUG, "%s/%d", locations[i].user->string, + (int) locations[i].exposure); } + } #endif - /* all done */ - return(quiet); + /* all done */ + return quiet; } /* @@ -953,89 +884,80 @@ ulogin_remove_user(notice, auth, who, err_return) static void ulogin_flush_user(notice) - ZNotice_t *notice; + ZNotice_t *notice; { - register ZLocation_t *loc, *loc2; - register int i, j, num_match, num_left; + Location *loc, *loc2; + int i, j, num_match, num_left; - i = num_match = num_left = 0; + i = num_match = num_left = 0; - if (!(loc2 = ulogin_find(notice, 0))) { + if (!(loc2 = ulogin_find(notice, 0))) { #if 0 - zdbug((LOG_DEBUG,"ul_rem: not here")); + zdbug((LOG_DEBUG,"ul_rem: not here")); #endif - return; - } - - /* compute # locations left in the list, after loc2 (inclusive) */ - num_left = num_locs - (loc2 - locations); + return; + } - START_CRITICAL_CODE; + /* compute # locations left in the list, after loc2 (inclusive) */ + num_left = num_locs - (loc2 - locations); - while (num_left && - !strcasecmp(loc2[num_match].zlt_user->string, + while (num_left && + !strcasecmp(loc2[num_match].user->string, notice->z_class_inst)) { - /* as long as we keep matching, march up the list */ - num_match++; - num_left--; - } - if (num_locs == num_match) { /* no other locations left */ + /* as long as we keep matching, march up the list */ + num_match++; + num_left--; + } + if (num_locs == num_match) { /* no other locations left */ #if 0 - zdbug((LOG_DEBUG,"last loc")); + zdbug((LOG_DEBUG,"last loc")); #endif - for (j = 0; j < num_match; j++) - free_loc(&locations[j]); /* free storage */ - xfree (locations); - locations = NULLZLT; - num_locs = 0; - END_CRITICAL_CODE; - return; - } - - loc = (ZLocation_t *) xmalloc((num_locs - num_match) * - sizeof(ZLocation_t)); - if (!loc) { - syslog(LOG_CRIT, "ul_rem alloc"); - abort(); - /*NOTREACHED*/ - } - - /* copy old entries */ - while (i < num_locs && &locations[i] < loc2) { - loc[i] = locations[i]; - i++; - } + for (j = 0; j < num_match; j++) + free_loc(&locations[j]); /* free storage */ + free (locations); + locations = NULL; + num_locs = 0; + return; + } + + loc = (Location *) malloc((num_locs - num_match) * sizeof(Location)); + if (!loc) { + syslog(LOG_CRIT, "ul_rem alloc"); + abort(); + } + + /* copy old entries */ + while (i < num_locs && &locations[i] < loc2) { + loc[i] = locations[i]; + i++; + } - for(j = 0; j < num_match; j++) { - free_loc(&locations[i]); - i++; - } + for(j = 0; j < num_match; j++) { + free_loc(&locations[i]); + i++; + } - /* copy the rest */ - while (i < num_locs) { - loc[i - num_match] = locations[i]; - i++; - } + /* copy the rest */ + while (i < num_locs) { + loc[i - num_match] = locations[i]; + i++; + } - xfree(locations); + free(locations); - locations = loc; - num_locs -= num_match; + locations = loc; + num_locs -= num_match; - END_CRITICAL_CODE; - #ifdef DEBUG - if (zdebug) { - register int i; + if (zdebug) { + int i; - for (i = 0; i < num_locs; i++) - syslog(LOG_DEBUG, "%s/%d", - locations[i].zlt_user->string, - (int) locations[i].zlt_exposure); + for (i = 0; i < num_locs; i++) { + syslog(LOG_DEBUG, "%s/%d", locations[i].user->string, + (int) locations[i].exposure); } + } #endif - /* all done */ - return; } /* @@ -1044,86 +966,85 @@ ulogin_flush_user(notice) static int ulogin_expose_user(notice, exposure) - ZNotice_t *notice; - exposure_type exposure; + ZNotice_t *notice; + Exposure_type exposure; { - ZLocation_t *loc, loc2; - int idx, notfound = 1; + Location *loc, loc2; + int idx, notfound = 1; #if 0 - zdbug((LOG_DEBUG,"ul_expose: %s type %d", notice->z_sender, - (int) exposure)); + zdbug((LOG_DEBUG,"ul_expose: %s type %d", notice->z_sender, + (int) exposure)); #endif - if (ulogin_parse(notice, &loc2)) - return(1); - - if (!(loc = ulogin_find(notice, 0))) { + loc = ulogin_find(notice, 0); + if (!loc) { #if 0 zdbug((LOG_DEBUG,"ul_hide: not here")); #endif - return(1); - } + return 1; + } + + if (ulogin_parse(notice, &loc2)) + return 1; - idx = loc -locations; - - while ((idx < num_locs) && - locations[idx].zlt_user == loc2.zlt_user) { - - /* change exposure and owner for each loc on that host */ - if (locations[idx].zlt_machine == loc2.zlt_machine) { - notfound = 0; - locations[idx].zlt_exposure = exposure; - locations[idx].zlt_port = notice->z_port; - /* change time for the specific loc */ - if (locations[idx].zlt_tty == loc2.zlt_tty) { - xfree(locations[idx].zlt_time); - locations[idx].zlt_time = strsave(loc2.zlt_time); - } - } - idx++; + idx = loc -locations; + + while (idx < num_locs && locations[idx].user == loc2.user) { + + /* change exposure and owner for each loc on that host */ + if (locations[idx].machine == loc2.machine) { + notfound = 0; + locations[idx].exposure = exposure; + locations[idx].addr.sin_port = notice->z_port; + /* change time for the specific loc */ + if (locations[idx].tty == loc2.tty) { + free(locations[idx].time); + locations[idx].time = strsave(loc2.time); + } } - return(notfound); + idx++; + } + + free_loc(&loc2); + return notfound; } static void ulogin_locate(notice, who, auth) - ZNotice_t *notice; - struct sockaddr_in *who; - int auth; + ZNotice_t *notice; + struct sockaddr_in *who; + int auth; { - char **answer; - int found; - Code_t retval; - struct sockaddr_in send_to_who; - - answer = ulogin_marshal_locs(notice, &found, auth); - - send_to_who = *who; - send_to_who.sin_port = notice->z_port; - - if ((retval = ZSetDestAddr(&send_to_who)) != ZERR_NONE) { - syslog(LOG_WARNING, "ulogin_locate set addr: %s", - error_message(retval)); - if (answer) - xfree(answer); - return; - } + char **answer; + int found; + Code_t retval; + struct sockaddr_in send_to_who; - notice->z_kind = ACKED; + answer = ulogin_marshal_locs(notice, &found, auth); - /* use xmit_frag() to send each piece of the notice */ + send_to_who = *who; + send_to_who.sin_port = notice->z_port; - if ((retval = ZSrvSendRawList(notice, answer, found*NUM_FIELDS, - xmit_frag)) - != ZERR_NONE) { - syslog(LOG_WARNING, "ulog_locate xmit: %s", - error_message(retval)); - } + retval = ZSetDestAddr(&send_to_who); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "ulogin_locate set addr: %s", + error_message(retval)); if (answer) - xfree(answer); + free(answer); return; + } + + notice->z_kind = ACKED; + + /* use xmit_frag() to send each piece of the notice */ + + retval = ZSrvSendRawList(notice, answer, found * NUM_FIELDS, xmit_frag); + if (retval != ZERR_NONE) + syslog(LOG_WARNING, "ulog_locate xmit: %s", error_message(retval)); + if (answer) + free(answer); } /* @@ -1133,151 +1054,243 @@ ulogin_locate(notice, who, auth) static char ** ulogin_marshal_locs(notice, found, auth) - ZNotice_t *notice; - register int *found; - int auth; + ZNotice_t *notice; + int *found; + int auth; { - ZLocation_t **matches = (ZLocation_t **) 0; - ZLocation_t *loc; - char **answer; - register int i = 0; - ZSTRING *inst; + Location **matches = (Location **) 0; + Location *loc; + char **answer; + int i = 0; + String *inst; + int local = sender_in_realm(notice); - *found = 0; /* # of matches */ + *found = 0; /* # of matches */ - if (!(loc = ulogin_find(notice, 0))) - /* not here anywhere */ - return((char **)0); + loc = ulogin_find(notice, 0); + if (!loc) + return(NULL); - i = loc - locations; + i = loc - locations; - inst = make_zstring(notice->z_class_inst,0); - while (i < num_locs && (inst == locations[i].zlt_user)) { - /* these locations match */ + inst = make_string(notice->z_class_inst,0); + while (i < num_locs && (inst == locations[i].user)) { + /* these locations match */ #if 0 - zdbug((LOG_DEBUG,"match %s", locations[i].zlt_user->string)); + zdbug((LOG_DEBUG,"match %s", locations[i].user->string)); #endif - switch (locations[i].zlt_exposure) { - case OPSTAFF_VIS: - i++; - continue; - case REALM_VIS: - case REALM_ANN: - if (!auth) { - i++; - continue; - } - case NET_VIS: - case NET_ANN: - default: - break; - } - if (!*found) { - if ((matches = (ZLocation_t **) xmalloc(sizeof(ZLocation_t *))) == (ZLocation_t **) 0) { - syslog(LOG_ERR, "ulog_loc: no mem"); - break; /* from the while */ - } - matches[0] = &locations[i]; - (*found)++; - } else { - if ((matches = (ZLocation_t **) realloc((caddr_t) matches, (unsigned) ++(*found) * sizeof(ZLocation_t *))) == (ZLocation_t **) 0) { - syslog(LOG_ERR, "ulog_loc: realloc no mem"); - *found = 0; - break; /* from the while */ - } - matches[*found - 1] = &locations[i]; - } + switch (locations[i].exposure) { + case OPSTAFF_VIS: + i++; + continue; + case REALM_VIS: + case REALM_ANN: + if (!local) { i++; + continue; + } + case NET_VIS: + case NET_ANN: + default: + break; } - free_zstring(inst); - - /* OK, now we have a list of user@host's to return to the client - in matches */ - + if (!*found) { + matches = (Location **) malloc(sizeof(Location *)); + if (!matches) { + syslog(LOG_ERR, "ulog_loc: no mem"); + break; /* from the while */ + } + matches[0] = &locations[i]; + (*found)++; + } else { + matches = (Location **) realloc(matches, + ++(*found) * sizeof(Location *)); + if (!matches) { + syslog(LOG_ERR, "ulog_loc: realloc no mem"); + *found = 0; + break; /* from the while */ + } + matches[*found - 1] = &locations[i]; + } + i++; + } + free_string(inst); + /* OK, now we have a list of user@host's to return to the client + in matches */ + + #ifdef DEBUG - if (zdebug) { - for (i = 0; i < *found ; i++) - zdbug((LOG_DEBUG,"found %s", - matches[i]->zlt_user->string)); - } + if (zdebug) { + for (i = 0; i < *found ; i++) + zdbug((LOG_DEBUG,"found %s", + matches[i]->user->string)); + } #endif - - /* coalesce the location information into a list of char *'s */ - if ((answer = (char **)xmalloc((*found) * NUM_FIELDS * sizeof(char *))) == (char **) 0) { - syslog(LOG_ERR, "zloc no mem(answer)"); - *found = 0; - } else - for (i = 0; i < *found ; i++) { - answer[i*NUM_FIELDS] = (char *) matches[i]->zlt_machine->string; - answer[i*NUM_FIELDS + 1] = (char *) matches[i]->zlt_time; - answer[i*NUM_FIELDS + 2] = (char *) matches[i]->zlt_tty->string; - } - - if (matches) - xfree(matches); - return(answer); + + /* coalesce the location information into a list of char *'s */ + answer = (char **) malloc((*found) * NUM_FIELDS * sizeof(char *)); + if (!answer) { + syslog(LOG_ERR, "zloc no mem(answer)"); + *found = 0; + } else + for (i = 0; i < *found ; i++) { + answer[i * NUM_FIELDS] = matches[i]->machine->string; + answer[i * NUM_FIELDS + 1] = matches[i]->time; + answer[i * NUM_FIELDS + 2] = matches[i]->tty->string; + } + + if (matches) + free(matches); + return answer; } void uloc_dump_locs(fp) - register FILE *fp; + FILE *fp; { - register int i; - char buf[BUFSIZ*3]; - static char *bufp; - static Zconst char *cp; - - /* delay using stdio so that we can run FAST! */ - for (i = 0; i < num_locs; i++) { - bufp = buf; -#define cpy(str) cp=(str);while(*cp){*bufp++ = *cp++;} - cpy (locations[i].zlt_user->string); - *bufp++ = '/'; - cpy (locations[i].zlt_machine->string); - *bufp++ = '/'; - cpy (locations[i].zlt_time); - *bufp++ = '/'; - cpy (locations[i].zlt_tty->string); - switch (locations[i].zlt_exposure) { - case OPSTAFF_VIS: - cpy ("/OPSTAFF/"); - break; - case REALM_VIS: - cpy ("/RLM_VIS/"); - break; - case REALM_ANN: - cpy ("/RLM_ANN/"); - break; - case NET_VIS: - cpy ("/NET_VIS/"); - break; - case NET_ANN: - cpy ("/NET_ANN/"); - break; - default: - sprintf (bufp, "/? %d ?/", locations[i].zlt_exposure); - while (*bufp) - bufp++; - break; - } - cpy (inet_ntoa (locations[i].zlt_addr)); - *bufp++ = '/'; - sprintf(bufp, "%d", ntohs(locations[i].zlt_port)); - fputs(buf, fp); - (void) putc('\n', fp); -#undef cpy + int i; + + for (i = 0; i < num_locs; i++) { + fputs("'", fp); + dump_quote(locations[i].user->string, fp); + fputs("' '", fp); + dump_quote(locations[i].machine->string, fp); + fputs("' '", fp); + dump_quote(locations[i].time, fp); + fputs("' ", fp); + switch (locations[i].exposure) { + case OPSTAFF_VIS: + fputs("OPSTAFF", fp); + break; + case REALM_VIS: + fputs("RLM_VIS", fp); + break; + case REALM_ANN: + fputs("RLM_ANN", fp); + break; + case NET_VIS: + fputs("NET_VIS", fp); + break; + case NET_ANN: + fputs("NET_ANN", fp); + break; + default: + fprintf(fp, "? %d ?", locations[i].exposure); + break; } - return; + fprintf(fp, " %s/%d\n", inet_ntoa(locations[i].addr.sin_addr), + ntohs(locations[i].addr.sin_port)); + } } static void free_loc(loc) - ZLocation_t *loc; + Location *loc; +{ + free_string(loc->user); + free_string(loc->machine); + free_string(loc->tty); + free(loc->time); + return; +} + +static void +ulogin_locate_forward(notice, who, realm) + ZNotice_t *notice; + struct sockaddr_in *who; + Realm *realm; { - free_zstring(loc->zlt_user); - free_zstring(loc->zlt_machine); - free_zstring(loc->zlt_tty); - xfree(loc->zlt_time); + ZNotice_t lnotice; + + lnotice = *notice; + lnotice.z_opcode = REALM_REQ_LOCATE; + + realm_handoff(&lnotice, 1, who, realm, 0); +} + +void +ulogin_realm_locate(notice, who, realm) + ZNotice_t *notice; + struct sockaddr_in *who; + Realm *realm; +{ + char **answer; + int found; + Code_t retval; + ZNotice_t lnotice; + char *pack; + int packlen; + +#ifdef DEBUG + if (zdebug) + zdbug((LOG_DEBUG, "ulogin_realm_locate")); +#endif + + answer = ulogin_marshal_locs(notice, &found, 0/*AUTH*/); + + lnotice = *notice; + lnotice.z_opcode = REALM_ANS_LOCATE; + + if ((retval = ZFormatRawNoticeList(&lnotice, answer, found * NUM_FIELDS, &pack, &packlen)) != ZERR_NONE) { + syslog(LOG_WARNING, "ulog_rlm_loc format: %s", + error_message(retval)); + + if (answer) + free(answer); + return; + } + if (answer) + free(answer); + + if ((retval = ZParseNotice(pack, packlen, &lnotice)) != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_rlm_sendit parse: %s", + error_message(retval)); + free(pack); + return; + } + + realm_handoff(&lnotice, 1, who, realm, 0); + free(pack); + return; } + +void +ulogin_relay_locate(notice, who) + ZNotice_t *notice; + struct sockaddr_in *who; +{ + ZNotice_t lnotice; + Code_t retval; + struct sockaddr_in newwho; + char *pack; + int packlen; + + newwho.sin_addr.s_addr = notice->z_sender_addr.s_addr; + newwho.sin_port = notice->z_port; + newwho.sin_family = AF_INET; + + if ((retval = ZSetDestAddr(&newwho)) != ZERR_NONE) { + syslog(LOG_WARNING, "uloc_relay_loc set addr: %s", + error_message(retval)); + return; + } + + lnotice = *notice; + lnotice.z_opcode = LOCATE_LOCATE; + lnotice.z_kind = ACKED; + + if ((retval = ZFormatRawNotice(&lnotice, &pack, &packlen)) != ZERR_NONE) { + syslog(LOG_WARNING, "ulog_relay_loc format: %s", + error_message(retval)); + return; + } + + if ((retval = ZSendPacket(pack, packlen, 0)) != ZERR_NONE) { + syslog(LOG_WARNING, "ulog_relay_loc xmit: %s", + error_message(retval)); + } + free(pack); +} + diff --git a/server/unix.h b/server/unix.h deleted file mode 100644 index 78b6d34..0000000 --- a/server/unix.h +++ /dev/null @@ -1,110 +0,0 @@ -/* This file is part of the Project Athena Zephyr Notification System. - * It contains declarations for many standard UNIX library functions, - * and macros for aiding in interfacing to them. - * - * Created by Ken Raeburn. - * - * $Source$ - * $Author$ - * $Zephyr: unix.h,v 1.3 91/01/28 15:12:57 raeburn Exp $ - * - * Copyright (c) 1990,1991 by the Massachusetts Institute of Technology. - * For copying and distribution information, see the file - * "mit-copyright.h". - */ - -#include <zephyr/mit-copyright.h> - -#ifndef ZSERVER_UNIX_H__ - -#include <stdio.h> -#if defined(__STDC__) && !defined(__HIGHC__) && !defined(SABER) -/* Brain-dead High-C claims to be ANSI but doesn't have the include files.. */ -#include <stdlib.h> -#endif - -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -#ifndef linux /* struct qelem is defined in stdlib.h */ -/* - * Queue-handling functions. This structure is basically a dummy; - * as long as the start of another structure looks like this, - * we're okay. - */ -struct qelem { - struct qelem *q_forw; - struct qelem *q_back; - char *q_data; -}; -void insque P((struct qelem*, struct qelem*)); -void remque P((struct qelem *)); - -#endif /* linux */ - -/* From the Error table library */ -char *error_message P((long)); - -#ifdef KERBEROS -/* Kerberos */ -extern int krb_get_lrealm P((char *, int)); -extern int dest_tkt P((void)); -extern int krb_get_svc_in_tkt P((char *, char *, char *, char *, char *, int, - char *)); -#ifdef KRB_DEFS /* have we actually got krb.h? */ -extern int krb_mk_req P((KTEXT, char *, char *, char *, unsigned long)); -extern int krb_get_cred P((char *, char *, char *, CREDENTIALS *)); -#endif -#else -extern int rresvport P((int *)); -#endif - -#ifdef HESIOD - /* Hesiod */ -extern char ** hes_resolve P((Zconst char *, Zconst char *)); -#endif - - /* hacked acl code */ -extern void acl_cache_reset P((void)); - -#undef P - -#ifdef vax -#define HAVE_ALLOCA -#endif - -#if defined (__GNUC__) - -/* GCC/G++ has a built-in function for allocating automatic storage. */ -#define LOCAL_ALLOC(X) __builtin_alloca(X) -#define LOCAL_FREE(X) - -#else /* not gcc or g++ */ - -#ifdef HAVE_ALLOCA -#define LOCAL_ALLOC(X) alloca(X) -#define LOCAL_FREE(X) -#endif -#endif - -#ifndef LOCAL_ALLOC -#define LOCAL_ALLOC(X) malloc(X) -#define LOCAL_FREE(X) free(X) -#endif - -/* - * Miscellaneous casts, so we don't have to insert these all over the - * source files... - */ - -#define xfree(foo) free((caddr_t) (foo)) -#define xinsque(a,b) insque((struct qelem *)(a), (struct qelem *)(b)) -#define xremque(a) remque((struct qelem *)(a)) -#define xmalloc(a) malloc((unsigned)(a)) -#define xrealloc(foo,a) realloc((caddr_t) (foo), (unsigned) (a)) - -#define ZSERVER_UNIX_H__ -#endif diff --git a/server/version.c b/server/version.c index 587028f..5487000 100644 --- a/server/version.c +++ b/server/version.c @@ -13,26 +13,22 @@ #include <zephyr/mit-copyright.h> -#include <string.h> -#include <zephyr/zephyr.h> +#include "zserver.h" #include "version.h" +const char zephyr_version[] = "Zephyr system version 2.0"; + #ifdef DEBUG -Zconst char version[] = "Zephyr Server (DEBUG) $Revision$"; +const char version[] = "Zephyr server (DEBUG) $Revision$"; #else -Zconst char version[] = "Zephyr Server $Revision$"; +const char version[] = "Zephyr server $Revision$"; #endif #if !defined (lint) && !defined (SABER) -Zconst char rcsid_version_c[] = +static const char rcsid_version_c[] = "$Id$"; -Zconst char copyright[] = +static const char copyright[] = "Copyright (c) 1987,1988,1989,1990 Massachusetts Institute of Technology.\n"; -#ifdef CONCURRENT -Zconst char concurrent[] = "Brain-dump concurrency enabled"; -#else -Zconst char concurrent[] = "no brain-dump concurrency"; -#endif #endif char * diff --git a/server/version.h b/server/version.h deleted file mode 100644 index 40f1ff3..0000000 --- a/server/version.h +++ /dev/null @@ -1 +0,0 @@ -#define ZSERVER_VERSION_STRING "(Fri Nov 19 13:34:58 EST 1993) probe@tardis" diff --git a/server/zalloc.c b/server/zalloc.c deleted file mode 100644 index f4e5e23..0000000 --- a/server/zalloc.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Memory allocator for Zephyr server. - */ - -#include <stdio.h> -#include <zephyr/zephyr.h> -#include "unix.h" -#include "zalloc.h" - -#ifndef MPROF -/* - * What's the maximum number of words to expect to allocate through - * this mechanism? (Larger requests will be fed to malloc.) - */ -#define MAX_SIZE 32 - -static void *free_space; -static unsigned int free_space_size; -static void *buckets[MAX_SIZE]; -#ifdef ZALLOC_STATS -enum zalloc_memtype { - FREE=0, ALLOCATED, - N_zalloc_memtype -}; -static int zalloc_count[MAX_SIZE][(int) N_zalloc_memtype]; -#endif - -/* - union misc_types { - void *void_p; - int i; - long l; - double d; - }; -*/ -/* SZ = sizeof(misc_types) */ -#define SZ 32 - -/* - * Pick some size here that will help keep down the number of calls to - * malloc, but doesn't waste too much space. To avoid waste of space, - * we leave some overhead before the next power of two. - */ - - -/* ALLOC_SIZE = ((16384 - 32) / SZ) * SZ */ -#define ALLOC_SIZE 16352 - -unsigned int round (size) - unsigned int size; -{ - size += SZ - 1; - size -= (size % SZ); - return size; -} - -#define ROUND(size) (size = round (size)) -int BUCKET (size) - unsigned int size; -{ - ROUND (size); - return size / SZ - 1; -} - -static void -zmemset (ptr, size, fill) - void *ptr; - int size; - int fill; -{ -#ifdef ZALLOC_DEBUG - char *cptr = (char *) ptr; - while (size--) - cptr[size] = fill; -#endif -} - -void * -zalloc (size) - unsigned int size; -{ - int bucket; - void *ret; - void **ptr; - - ROUND (size); - bucket = BUCKET (size); - if (bucket < 0 || bucket >= MAX_SIZE) - return (void *) malloc (size); - - ptr = &buckets[bucket]; -#ifdef ZALLOC_DEBUG_PRINT - fprintf (stderr, "zalloc(%d); looking in bucket %d, found %08X\n", - size, bucket, *ptr); -#endif - if (*ptr) { - ret = *ptr; - *ptr = *(void**)ret; - goto return_it; - } - - if (free_space_size < size) { - if (free_space_size > 0) { - ptr = &buckets[BUCKET (free_space_size)]; - *(void**)free_space = *ptr; - *ptr = free_space; -#ifdef ZALLOC_DEBUG_PRINT - fprintf (stderr, "tossing %08X into bucket %d\n", - free_space, bucket); -#endif -#ifdef ZALLOC_STATS - zalloc_count[BUCKET (free_space_size)][FREE]++; -#endif - } - - free_space_size = ALLOC_SIZE; - free_space = (void *) malloc (free_space_size); - if (!free_space) - abort (); -#ifdef ZALLOC_DEBUG_PRINT - fprintf (stderr, "grabbing more free store at %08X\n", free_space); -#endif - } - - ret = free_space; - free_space = (char *) free_space + size; - free_space_size -= size; -return_it: -#ifdef ZALLOC_DEBUG_PRINT - fprintf (stderr, "returning %08X\n", ret); -#endif - zmemset (ret, size, 0xe5); -#ifdef ZALLOC_STATS - zalloc_count[bucket][FREE]--, zalloc_count[bucket][ALLOCATED]++; -#endif - return ret; -} - -void zfree (ptr, size) - void *ptr; - unsigned int size; -{ - int bucket; - void **b; - - ROUND (size); - bucket = BUCKET (size); - if (bucket < 0 || bucket >= MAX_SIZE) { - free (ptr); - return; - } - - b = &buckets[bucket]; - zmemset (ptr, size, 0xe5); - *(void **) ptr = *b; - *b = ptr; -#ifdef ZALLOC_DEBUG -#ifdef ZALLOC_DEBUG_PRINT - fprintf (stderr, "putting %08X into bucket %d\n", - ptr, bucket); - fprintf (stderr, "bucket %d:"); - for (ptr = buckets[bucket]; ptr; ptr=*(void**)ptr) - fprintf (stderr, " %X", ptr); - fprintf (stderr, "\n"); -#else - for (ptr = buckets[bucket]; ptr; ptr=*(void**)ptr) - /* do nothing, just read value */; -#endif -#endif - -#ifdef ZALLOC_STATS - zalloc_count[bucket][FREE]++, zalloc_count[bucket][ALLOCATED]--; -#endif -} -#endif diff --git a/server/zalloc.h b/server/zalloc.h deleted file mode 100644 index a2c60a8..0000000 --- a/server/zalloc.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - */ - -#ifndef __zalloc_h -#define __zalloc_h __FILE__ -#ifdef MPROF -#define zalloc(sz) malloc(sz) -#define zfree(p,sz) free(p) -#else - -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif /* STDC */ - -extern void * zalloc P((unsigned int)); -extern void zfree P((void *, unsigned int)); - -#undef P -#endif /* MPROF */ -#endif /* __zalloc_h */ diff --git a/server/zserver.h b/server/zserver.h index 8dede2b..4fe7c2a 100644 --- a/server/zserver.h +++ b/server/zserver.h @@ -16,27 +16,9 @@ #include <zephyr/mit-copyright.h> -#include <zephyr/zephyr.h> /* which includes <errno.h>, - <sys/types.h>, - <netinet/in.h>, - <sys/time.h>, - <stdio.h>, - <krb.h> */ +#include <internal.h> #include <arpa/inet.h> -#include <zephyr/acl.h> -#include <sys/file.h> -#include <fcntl.h> - -#include <zephyr/zsyslog.h> - -#include <string.h> -#include <signal.h> -#ifdef lint -#include <sys/uio.h> /* so it shuts up about struct iovec */ -#endif /* lint */ -#ifdef _IBMR2 -#include <sys/select.h> -#endif + #include "zsrv_err.h" #include "timer.h" @@ -44,277 +26,299 @@ #include "zstring.h" #include "access.h" -#include "unix.h" -#include "zalloc.h" +#include "acl.h" -/* definitions for the Zephyr server */ - -/* structures */ +/* For krb_rd_req prototype and definition. */ +#ifndef KRB_INT32 +#define KRB_INT32 ZEPHYR_INT32 +#endif -/* - * ZDestination: Where is this notice going to? This includes class, - * instance, and recipient at the moment. - */ +/* These macros are for insertion into and deletion from a singly-linked list + * with back pointers to the previous element's next pointer. In order to + * make these macros act like expressions, they use the comma operator for + * sequenced evaluations of assignment, and "a && b" for "evaluate assignment + * b if expression a is true". */ +#define LIST_INSERT(head, elem) \ + ((elem)->next = *(head), \ + (*head) && ((*(head))->prev_p = &(elem)->next), \ + (*head) = (elem), (elem)->prev_p = (head)) +#define LIST_DELETE(elem) \ + (*(elem)->prev_p = (elem)->next, \ + (elem)->next && ((elem)->next->prev_p = (elem)->prev_p)) + +/* Current time as cached by main(); use instead of time(). */ +#define NOW t_local.tv_sec + +#ifdef ZEPHYR_USES_KERBEROS +#ifndef NOENCRYPTION +/* Kerberos shouldn't stick us with array types... */ +typedef struct { + des_key_schedule s; +} Sched; +#endif +#endif -typedef struct _ZDestination { - ZSTRING *classname; - ZSTRING *inst; - ZSTRING *recip; -} ZDestination; - -/* typedef struct _Notice { - ZNotice_t *notice; - struct _ZDestination dest; - ZSTRING *sender; - int msg_no; -} Notice; -*/ -typedef struct _ZSubscr_t { - struct _ZSubscr_t *q_forw; /* links in client's subscr. queue */ - struct _ZSubscr_t *q_back; - struct _ZDestination zst_dest; /* destination of messages */ -} ZSubscr_t; - -typedef struct _ZClient_t { - struct sockaddr_in zct_sin; /* ipaddr/port of client */ - struct _ZSubscr_t *zct_subs; /* subscriptions */ -#ifdef KERBEROS - C_Block zct_cblock; /* session key for this client */ -#endif /* KERBEROS */ - ZSTRING *zct_principal; /* krb principal of user */ - long last_msg; /* last message sent to this client */ - long last_check; /* actually, last time the other - server was asked to check... */ - int last_send; /* The send counter value for the - * last packet sent to the client, - * used to prevent duplicates. See - * sendit() in dispatch.c. */ -} ZClient_t; - -typedef struct _ZClientList_t { - struct _ZClientList_t *q_forw; - struct _ZClientList_t *q_back; - struct _ZClient_t *zclt_client; -} ZClientList_t; - -typedef struct _ZTriplet_t { - struct _ZTriplet_t *q_forw; - struct _ZTriplet_t *q_back; - ZDestination zct_dest; - ZAcl_t *zct_acl; - ZClientList_t *zct_clientlist; -} ZTriplet_t; - -typedef struct _ZHostList_t { - struct _ZHostList_t *q_forw; - struct _ZHostList_t *q_back; - ZClientList_t *zh_clients; - struct sockaddr_in zh_addr; /* IP addr/port of hostmanager */ - unsigned int zh_locked; /* 1 if this host is locked for - a braindump */ -} ZHostList_t; - -typedef enum _server_state { - SERV_UP, /* Server is up */ - SERV_TARDY, /* Server due for a hello */ - SERV_DEAD, /* Server is considered dead */ - SERV_STARTING /* Server is between dead and up */ -} server_state; - -typedef struct _ZNotAcked_t { - struct _ZNotAcked_t *q_forw; /* link to next */ - struct _ZNotAcked_t *q_back; /* link to prev */ - timer na_timer; /* timer for retransmit */ - long na_abstimo; /* absolute timeout to drop after */ - short na_rexmits; /* number of retransmits */ - short na_packsz; /* size of packet */ - caddr_t na_packet; /* ptr to packet */ - ZUnique_Id_t na_uid; /* uid of packet */ - union { /* address to send to */ - struct sockaddr_in na_sin; /* client address */ - int srv_idx; /* index of server */ - } dest; -#define na_addr dest.na_sin -#define na_srv_idx dest.srv_idx -} ZNotAcked_t; - -typedef struct _ZSrvPending_t { - struct _ZSrvPending_t *q_forw; /* link to next */ - struct _ZSrvPending_t *q_back; /* link to prev */ - caddr_t pend_packet; /* the notice (in pkt form) */ - short pend_len; /* len of pkt */ - unsigned int pend_auth; /* whether it is authentic */ - struct sockaddr_in pend_who; /* the addr of the sender */ -} ZSrvPending_t; - -typedef struct _ZServerDesc_t { - server_state zs_state; /* server's state */ - struct sockaddr_in zs_addr; /* server's address */ - long zs_timeout; /* Length of timeout in sec */ - timer zs_timer; /* timer struct for this server */ - struct _ZHostList_t *zs_hosts; /* pointer to list of info from this - server */ - struct _ZSrvPending_t *zs_update_queue; /* queue of packets to send +typedef struct _Destination Destination; +typedef struct _Destlist Destlist; +typedef struct _Realm Realm; +typedef struct _Realmname Realmname; +typedef struct _Client Client; +typedef struct _Triplet Triplet; +typedef enum _Server_state Server_state; +typedef struct _Unacked Unacked; +typedef struct _Pending Pending; +typedef struct _Server Server; +typedef enum _Sent_type Sent_type; +typedef struct _Statistic Statistic; + +struct _Destination { + String *classname; + String *inst; + String *recip; +}; + +struct _Destlist { + Destination dest; + struct _Destlist *next, **prev_p; +}; + +struct _Realm { + char name[REALM_SZ]; + int count; + struct sockaddr_in *addrs; + int idx; /* which server we are connected to */ + Destlist *subs; + Client *client; + long tkt_try; +}; + +struct _Realmname { + char name[REALM_SZ]; + char **servers; + int nused; + int nservers; +}; + +struct _Client { + struct sockaddr_in addr; /* ipaddr/port of client */ + Destlist *subs ; /* subscriptions */ +#ifdef ZEPHYR_USES_KERBEROS + C_Block session_key; /* session key for this client */ +#endif /* ZEPHYR_USES_KERBEROS */ + String *principal; /* krb principal of user */ + time_t last_check; /* last time the other server was + asked to check */ + long last_msg; /* last message sent to this client */ + int last_send; /* Counter for last sent packet. */ + Realm *realm; + struct _Client *next, **prev_p; +}; + +struct _Triplet { + Destination dest; + Acl *acl; + Client **clients; + int clients_size; + struct _Triplet *next, **prev_p; +}; + +enum _Server_state { + SERV_UP, /* Server is up */ + SERV_TARDY, /* Server due for a hello */ + SERV_DEAD, /* Server is considered dead */ + SERV_STARTING /* Server is between dead and up */ +}; + +struct _Unacked { + Timer *timer; /* timer for retransmit */ + short rexmits; /* number of retransmits */ + short packsz; /* size of packet */ + char *packet; /* ptr to packet */ + ZUnique_Id_t uid; /* uid of packet */ + struct sockaddr_in ack_addr; + union { /* address to send to */ + struct sockaddr_in addr; /* client address */ + int srv_idx; /* index of server */ + struct { + int rlm_idx; /* index of realm */ + int rlm_srv_idx; /* index of server in realm */ + } rlm; + } dest; + struct _Unacked *next, **prev_p; +}; + +struct _Pending { + char *packet; /* the notice (in pkt form) */ + short len; /* len of pkt */ + unsigned int auth; /* whether it is authentic */ + struct sockaddr_in who; /* the addr of the sender */ + struct _Pending *next; +}; + +struct _Server { + Server_state state; /* server's state */ + struct sockaddr_in addr; /* server's address */ + long timeout; /* Length of timeout in sec */ + Timer *timer; /* timer for this server */ + Pending *queue; /* queue of packets to send to this server when done dumping */ - short zs_numsent; /* number of hello's sent */ - unsigned int zs_dumping; /* 1 if dumping, so we should queue */ - char addr[16]; /* text version of address */ -} ZServerDesc_t; - -typedef enum ZSentType { - NOT_SENT, /* message was not xmitted */ - SENT, /* message was xmitted */ - AUTH_FAILED, /* authentication failed */ - NOT_FOUND /* user not found for uloc */ -} ZSentType; + Pending *queue_last; /* last packet on queue */ + short num_hello_sent; /* number of hello's sent */ + unsigned int dumping; /* 1 if dumping, so we should queue */ + char addr_str[16]; /* text version of address */ +}; + +enum _Sent_type { + NOT_SENT, /* message was not xmitted */ + SENT, /* message was xmitted */ + AUTH_FAILED, /* authentication failed */ + NOT_FOUND /* user not found for uloc */ +}; /* statistics gathering */ -typedef struct _ZStatistic_t { - int val; - char *str; -} ZStatistic; - -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif +struct _Statistic { + int val; + char *str; +}; /* Function declarations */ /* found in bdump.c */ -extern void bdump_get P((ZNotice_t *notice, int auth, struct sockaddr_in *who, - ZServerDesc_t *server)); -extern void bdump_send P((void)); -extern void bdump_offer P((struct sockaddr_in *who)); -extern Code_t bdump_send_list_tcp P((ZNotice_Kind_t kind, int port, - char *class_name, char *inst, char *opcode, - char *sender, char *recip, - char **lyst, int num)); +void bdump_get __P((ZNotice_t *notice, int auth, struct sockaddr_in *who, + Server *server)); +void bdump_send __P((void)); +void bdump_offer __P((struct sockaddr_in *who)); +Code_t bdump_send_list_tcp __P((ZNotice_Kind_t kind, struct sockaddr_in *addr, + char *class_name, char *inst, char *opcode, + char *sender, char *recip, char **lyst, + int num)); +int get_tgt __P((void)); /* found in class.c */ -extern Code_t triplet_register P((ZClient_t *client, ZDestination *dest)); -extern Code_t triplet_deregister P((ZClient_t *client, ZDestination *dest)); -extern Code_t class_restrict P((char *z_class, ZAcl_t *acl)); -extern Code_t class_setup_restricted P((char *z_class, ZAcl_t *acl)); -extern ZClientList_t *triplet_lookup P((ZDestination *dest)); -extern ZAcl_t *class_get_acl P((ZSTRING *z_class)); -extern void class_free P((ZClientList_t *lyst)); -extern ZSTRING *class_control, *class_admin, *class_hm; -extern ZSTRING *class_ulogin, *class_ulocate; -extern void set_ZDestination_hash P((ZDestination *zd)); -extern int ZDest_eq P((ZDestination *zd1, ZDestination *zd2)); -extern int order_dest_strings P((ZDestination *zd1, ZDestination *zd2)); -extern void class_dump_subs P((register FILE *fp)); +extern String *class_control, *class_admin, *class_hm; +extern String *class_ulogin, *class_ulocate; +int ZDest_eq __P((Destination *d1, Destination *d2)); +Code_t triplet_register __P((Client *client, Destination *dest, Realm *realm)); +Code_t triplet_deregister __P((Client *client, Destination *dest, + Realm *realm)); +Code_t class_restrict __P((char *class, Acl *acl)); +Code_t class_setup_restricted __P((char *class, Acl *acl)); +Client **triplet_lookup __P((Destination *dest)); +Acl *class_get_acl __P((String *class)); +int dest_eq __P((Destination *d1, Destination *d2)); +int order_dest_strings __P((Destination *d1, Destination *d2)); +void triplet_dump_subs __P((FILE *fp)); /* found in client.c */ -extern Code_t client_register P((ZNotice_t *notice, struct sockaddr_in *who, - register ZClient_t **client, - ZServerDesc_t *server, int wantdefaults)); -extern void client_deregister P((ZClient_t *client, ZHostList_t *host, - int flush)); -extern void client_dump_clients P((FILE *fp, ZClientList_t *clist)); -extern ZClient_t *client_which_client P((struct sockaddr_in *who, - ZNotice_t *notice)); +Code_t client_register __P((ZNotice_t *notice, struct in_addr *host, + Client **client_p, int wantdefaults)); +void client_deregister __P((Client *client, int flush)); +void client_flush_host __P((struct in_addr *host)); +void client_dump_clients __P((FILE *fp)); +Client *client_which_client __P((struct in_addr *host, ZNotice_t *notice)); +Code_t client_send_clients __P((void)); /* found in common.c */ -extern char *strsave P((Zconst char *str)); -extern unsigned long hash P((Zconst char *)); -extern void subscr_quote P((char *p, FILE *fp)); +char *strsave __P((const char *str)); +unsigned long hash __P((const char *)); +void dump_quote __P((char *p, FILE *fp)); /* found in dispatch.c */ -extern void handle_packet P((void)); -extern void clt_ack P((ZNotice_t *notice, struct sockaddr_in *who, - ZSentType sent)); -extern void nack_release P((ZClient_t *client)); -extern void sendit P((register ZNotice_t *notice, int auth, - struct sockaddr_in *who)); -extern void rexmit P((void *)); -extern void xmit P((register ZNotice_t *notice, struct sockaddr_in *dest, - int auth, ZClient_t *client)); -extern Code_t control_dispatch P((ZNotice_t *notice, int auth, - struct sockaddr_in *who, - ZServerDesc_t *server)); -extern Code_t xmit_frag P((ZNotice_t *notice, char *buf, int len, - int waitforack)); - -/* found in hostm.c */ -extern void hostm_flush P((ZHostList_t *host, ZServerDesc_t *server)); -extern void hostm_shutdown P((void)); -extern void hostm_losing P((ZClient_t *client, ZHostList_t *host)); -extern ZHostList_t *hostm_find_host P((struct in_addr *addr)); -extern ZServerDesc_t *hostm_find_server P((struct in_addr *addr)); -extern void hostm_transfer P((ZHostList_t *host, ZServerDesc_t *server)); -extern void hostm_deathgram P((struct sockaddr_in *sin, - ZServerDesc_t *server)); -extern void hostm_dump_hosts P((FILE *fp)); -extern Code_t hostm_dispatch P((ZNotice_t *notice, int auth, - struct sockaddr_in *who, ZServerDesc_t *server)); -extern void hostm_lose_ignore P((ZClient_t *client)); -extern void hostm_renumber_servers P((int *)); +void handle_packet __P((void)); +void clt_ack __P((ZNotice_t *notice, struct sockaddr_in *who, Sent_type sent)); +void nack_release __P((Client *client)); +void sendit __P((ZNotice_t *notice, int auth, struct sockaddr_in *who, + int external)); +void rexmit __P((void *)); +void xmit __P((ZNotice_t *notice, struct sockaddr_in *dest, int auth, + Client *client)); +Code_t hostm_dispatch __P((ZNotice_t *notice, int auth, + struct sockaddr_in *who, Server *server)); +Code_t control_dispatch __P((ZNotice_t *notice, int auth, + struct sockaddr_in *who, Server *server)); +Code_t xmit_frag __P((ZNotice_t *notice, char *buf, int len, int waitforack)); +void hostm_shutdown __P((void)); /* found in kstuff.c */ -#ifdef KERBEROS -extern int GetKerberosData P((int, struct in_addr, AUTH_DAT*, char*, char*)); -extern Code_t SendKerberosData P((int, KTEXT, char*, char*)); +#ifdef ZEPHYR_USES_KERBEROS +int GetKerberosData __P((int, struct in_addr, AUTH_DAT *, char *, char *)); +Code_t SendKerberosData __P((int, KTEXT, char *, char *)); +void sweep_ticket_hash_table __P((void *)); #endif -/* found in server.c */ -extern void server_timo P((void *which)); -extern void server_recover P((ZClient_t *client)), - server_dump_servers P((FILE *fp)); -extern void server_init P((void)), - server_shutdown P((void)); -extern void server_forward P((ZNotice_t *notice, int auth, - struct sockaddr_in *who)); -extern void server_kill_clt P((ZClient_t *client)); -extern void server_pending_free P((register ZSrvPending_t *pending)); -extern void server_self_queue P((ZNotice_t*, int, struct sockaddr_in *)), - server_send_queue P((ZServerDesc_t *)), - server_reset P((void)); -extern int is_server(); -extern ZServerDesc_t *server_which_server P((struct sockaddr_in *who)); -extern ZSrvPending_t *server_dequeue P((register ZServerDesc_t *server)); -extern Code_t server_dispatch P((ZNotice_t *notice, int auth, - struct sockaddr_in *who)); -extern Code_t server_adispatch P((ZNotice_t *notice, int auth, - struct sockaddr_in *who, - ZServerDesc_t *server)); +/* found in kopt.c */ +#ifdef ZEPHYR_USES_KERBEROS +#ifndef NOENCRYPTION +Sched *check_key_sched_cache __P((des_cblock key)); +void add_to_key_sched_cache __P((des_cblock key, Sched *sched)); +int krb_set_key __P((char *key, int cvt)); +int krb_rd_req __P((KTEXT authent, char *service, char *instance, + unsigned KRB_INT32 from_addr, AUTH_DAT *ad, char *fn)); +int krb_find_ticket __P((KTEXT authent, KTEXT ticket)); +int krb_get_lrealm __P((char *r, int n)); +#endif +#endif +/* found in server.c */ +void server_timo __P((void *which)); +void server_dump_servers __P((FILE *fp)); +void server_init __P((void)); +void server_shutdown __P((void)); +void server_forward __P((ZNotice_t *notice, int auth, + struct sockaddr_in *who)); +void server_kill_clt __P((Client *client)); +void server_pending_free __P((Pending *pending)); +void server_self_queue __P((ZNotice_t *, int, struct sockaddr_in *)); +void server_send_queue __P((Server *)); +void server_reset __P((void)); +int is_server(); +Server *server_which_server __P((struct sockaddr_in *who)); +Pending *server_dequeue __P((Server *server)); +Code_t server_dispatch __P((ZNotice_t *notice, int auth, + struct sockaddr_in *who)); +Code_t server_adispatch __P((ZNotice_t *notice, int auth, + struct sockaddr_in *who, Server *server)); /* found in subscr.c */ -extern Code_t subscr_cancel P((struct sockaddr_in *sin, ZNotice_t *notice)); -extern Code_t subscr_subscribe P((ZClient_t *who, ZNotice_t *notice)), - subscr_send_subs P((ZClient_t *client, char *vers));; -extern void subscr_free_list P((ZClientList_t *list)), - subscr_cancel_client P((register ZClient_t *client)), - subscr_sendlist P((ZNotice_t *notice, int auth, struct sockaddr_in *who)); -extern void subscr_dump_subs P((FILE *fp, ZSubscr_t *subs)), - subscr_reset P((void)); -extern int compare_subs P((ZSubscr_t *s1, ZSubscr_t *s2, int do_wildcard)); -extern Code_t subscr_def_subs P((ZClient_t *who)); +Code_t subscr_cancel __P((struct sockaddr_in *sin, ZNotice_t *notice)); +Code_t subscr_subscribe __P((Client *who, ZNotice_t *notice)); +Code_t subscr_send_subs __P((Client *client)); +void subscr_cancel_client __P((Client *client)); +void subscr_sendlist __P((ZNotice_t *notice, int auth, + struct sockaddr_in *who)); +void subscr_dump_subs __P((FILE *fp, Destlist *subs)); +void subscr_reset __P((void)); +Code_t subscr_def_subs __P((Client *who)); /* found in uloc.c */ -extern void uloc_hflush P((struct in_addr *addr)), - uloc_flush_client P((struct sockaddr_in *sin)), - uloc_dump_locs P((register FILE *fp)); -extern Code_t ulogin_dispatch P((ZNotice_t *notice, int auth, - struct sockaddr_in *who, ZServerDesc_t *server)), - ulocate_dispatch P((ZNotice_t *notice, int auth, struct sockaddr_in *who, - ZServerDesc_t *server)), - uloc_send_locations P((ZHostList_t *host, char *vers)); +void uloc_hflush __P((struct in_addr *addr)); +void uloc_flush_client __P((struct sockaddr_in *sin)); +void uloc_dump_locs __P((FILE *fp)); +Code_t ulogin_dispatch __P((ZNotice_t *notice, int auth, + struct sockaddr_in *who, Server *server)); +Code_t ulocate_dispatch __P((ZNotice_t *notice, int auth, + struct sockaddr_in *who, Server *server)); +Code_t uloc_send_locations __P((void)); + +/* found in realm.c */ +Realm *realm_which_realm __P((struct sockaddr_in *who)); +Realm *realm_get_realm_by_name __P((char *name)); +void realm_handoff(ZNotice_t *, int, struct sockaddr_in *, Realm *, int); +char *realm_expand_realm(char *); +void realm_init __P((void)); +Code_t ZCheckRealmAuthentication __P((ZNotice_t *, struct sockaddr_in *, + char *)); /* found in version.c */ -extern char *get_version P((void)); - -#undef P - +char *get_version __P((void)); /* global identifiers */ /* found in main.c */ -extern struct sockaddr_in sock_sin; /* socket descriptors */ -extern u_short hm_port; /* port # of hostmanagers */ +int packets_waiting __P((void)); +extern struct sockaddr_in srv_addr; /* server socket address */ +extern unsigned short hm_port; /* host manager receiver port */ +extern unsigned short hm_srv_port; /* host manager server sending port */ extern int srv_socket; /* dgram sockets for clients and other servers */ extern int bdump_socket; /* brain dump socket @@ -322,31 +326,41 @@ extern int bdump_socket; /* brain dump socket extern fd_set interesting; /* the file descrips we are listening to right now */ -extern int nfildes; /* number to look at in select() */ +extern int nfds; /* number to look at in select() */ extern int zdebug; extern char myname[]; /* domain name of this host */ -extern ZNotAcked_t *nacklist; /* list of not ack'ed packets */ -extern Zconst char version[]; +#ifndef ZEPHYR_USES_HESIOD +extern char list_file[]; +#endif +#ifdef ZEPHYR_USES_KERBEROS +extern char srvtab_file[]; +extern char my_realm[]; +#endif +extern char acl_dir[]; +extern char subs_file[]; +extern const char version[]; extern u_long npackets; /* num of packets processed */ -extern long uptime; /* time we started */ +extern time_t uptime; /* time we started */ extern struct in_addr my_addr; +extern struct timeval t_local; /* current time */ /* found in bdump.c */ -extern int bdumping; /* are we dumping right now? */ +extern int bdumping; /* are we processing a bdump packet? */ +extern int bdump_concurrent; /* set while processing a packet + * concurrently during a braindump. */ /* found in dispatch.c */ -extern ZStatistic i_s_ctls, i_s_logins, i_s_admins, i_s_locates; -extern int num_rexmits; -extern long rexmit_secs, abs_timo; +extern Statistic i_s_ctls, i_s_logins, i_s_admins, i_s_locates; +extern int rexmit_times[]; /* found in server.c */ -extern ZServerDesc_t *otherservers; /* array of servers */ +extern Server *otherservers; /* array of servers */ extern int me_server_idx; /* me (in the array of servers) */ extern int nservers; /* number of other servers*/ /* found in subscr.c */ -extern ZSTRING *empty; -extern ZSTRING *wildcard_instance; +extern String *empty; +extern String *wildcard_instance; extern struct in_addr my_addr; /* my inet address */ @@ -363,24 +377,12 @@ extern struct in_addr my_addr; /* my inet address */ #define ADMIN_DONE "DUMP_DONE" /* Opcode: brain dump for this server is complete */ #define ADMIN_NEWCLT "NEXT_CLIENT" /* Opcode: this is a new client */ -#define ADMIN_LOST_CLT "LOST_CLIENT" /* Opcode: client not ack'ing */ #define ADMIN_KILL_CLT "KILL_CLIENT" /* Opcode: client is dead, remove */ #define ADMIN_STATUS "STATUS" /* Opcode: please send status */ -#define ADMIN_LIMBO "LIMBO" /* Class inst: please send limbo info*/ -#define ADMIN_YOU "YOUR_STATE" /* Class inst: please send your state*/ -#define ADMIN_ME "MY_STATE" /* Class inst: please send my info */ - -#define NULLZT ((ZTriplet_t *) 0) -#define NULLZCNT ((ZClient_t *) 0) -#define NULLZCLT ((ZClientList_t *) 0) -#define NULLZST ((ZSubscr_t *) 0) -#define NULLZHLT ((ZHostList_t *) 0) -#define NULLZNAT ((ZNotAcked_t *) 0) -#define NULLZACLT ((ZAcl_t *) 0) -#define NULLZPT ((ZPacket_t *) 0) -#define NULLZSDT ((ZServerDesc_t *) 0) -#define NULLZSPT ((ZSrvPending_t *) 0) +#define ADMIN_NEWREALM "NEXT_REALM" /* Opcode: this is a new realm */ +#define REALM_REQ_LOCATE "REQ_LOCATE" /* Opcode: request a location */ +#define REALM_ANS_LOCATE "ANS_LOCATE" /* Opcode: answer to location */ /* me_server_idx is the index into otherservers of this server descriptor. */ /* the 'limbo' server is always the first server */ @@ -389,11 +391,12 @@ extern struct in_addr my_addr; /* my inet address */ #define limbo_server_idx() (0) #define limbo_server (&otherservers[limbo_server_idx()]) -#define msgs_queued() (ZQLength() || otherservers[me_server_idx].zs_update_queue) +#define msgs_queued() (ZQLength() || otherservers[me_server_idx].queue) #define ack(a,b) clt_ack(a,b,SENT) #define nack(a,b) clt_ack(a,b,NOT_SENT) +#define min(a,b) ((a) < (b) ? (a) : (b)) #define max(a,b) ((a) > (b) ? (a) : (b)) #define START_CRITICAL_CODE @@ -402,18 +405,6 @@ extern struct in_addr my_addr; /* my inet address */ /* the instance that matches all instances */ #define WILDCARD_INSTANCE "*" -/* SERVER_SRVTAB is defined in zephyr.h */ -#define ZEPHYR_SRVTAB SERVER_SRVTAB - -#ifdef KERBEROS -#ifndef NOENCRYPTION -/* Kerberos shouldn't stick us with array types... */ -typedef struct { - des_key_schedule s; -} Sched; -#endif -#endif - /* debugging macros */ #ifdef DEBUG #define zdbug(s1) if (zdebug) syslog s1; diff --git a/server/zserver.h.auth b/server/zserver.h.auth deleted file mode 100644 index 41f6380..0000000 --- a/server/zserver.h.auth +++ /dev/null @@ -1,425 +0,0 @@ -#ifndef __ZSERVER_H__ -#define __ZSERVER_H__ -/* This file is part of the Project Athena Zephyr Notification System. - * It contains declarations for use in the server. - * - * Created by: John T. Kohl - * - * $Source$ - * $Author$ - * $Zephyr: /mit/zephyr/src/server/RCS/zserver.h,v 1.34 91/03/08 12:53:24 raeburn Exp $ - * - * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology. - * For copying and distribution information, see the file - * "mit-copyright.h". - */ - -#include <zephyr/mit-copyright.h> - -#include <zephyr/zephyr.h> /* which includes <errno.h>, - <sys/types.h>, - <netinet/in.h>, - <sys/time.h>, - <stdio.h>, - <krb.h> */ -#include <arpa/inet.h> -#include <zephyr/acl.h> -#include <sys/file.h> -#include <fcntl.h> - -#include <zephyr/zsyslog.h> - -#include <string.h> -#include <signal.h> -#ifdef lint -#include <sys/uio.h> /* so it shuts up about struct iovec */ -#endif /* lint */ -#ifdef _IBMR2 -#include <sys/select.h> -#endif -#include "zsrv_err.h" - -#include "timer.h" -#include "zsrv_conf.h" /* configuration params */ - -#include "zstring.h" -#include "access.h" -#include "unix.h" -#include "zalloc.h" - -/* definitions for the Zephyr server */ - -/* structures */ - -/* - * ZDestination: Where is this notice going to? This includes class, - * instance, and recipient at the moment. - */ - -typedef struct _ZDestination { - ZSTRING *classname; - ZSTRING *inst; - ZSTRING *recip; -} ZDestination; - -/* typedef struct _Notice { - ZNotice_t *notice; - struct _ZDestination dest; - ZSTRING *sender; - int msg_no; -} Notice; -*/ -typedef struct _ZSubscr_t { - struct _ZSubscr_t *q_forw; /* links in client's subscr. queue */ - struct _ZSubscr_t *q_back; - struct _ZDestination zst_dest; /* destination of messages */ -} ZSubscr_t; - -typedef struct _ZClient_t { - struct sockaddr_in zct_sin; /* ipaddr/port of client */ - struct _ZSubscr_t *zct_subs; /* subscriptions */ -#ifdef KERBEROS - C_Block zct_cblock; /* session key for this client */ -#endif /* KERBEROS */ - ZSTRING *zct_principal; /* krb principal of user */ - long last_msg; /* last message sent to this client */ - long last_check; /* actually, last time the other - server was asked to check... */ - int last_send; /* The send counter value for the - * last packet sent to the client, - * used to prevent duplicates. See - * sendit() in dispatch.c. */ -} ZClient_t; - -typedef struct _ZClientList_t { - struct _ZClientList_t *q_forw; - struct _ZClientList_t *q_back; - struct _ZClient_t *zclt_client; -} ZClientList_t; - -typedef struct _ZTriplet_t { - struct _ZTriplet_t *q_forw; - struct _ZTriplet_t *q_back; - ZDestination zct_dest; - ZAcl_t *zct_acl; - ZClientList_t *zct_clientlist; -} ZTriplet_t; - -typedef struct _ZHostList_t { - struct _ZHostList_t *q_forw; - struct _ZHostList_t *q_back; - ZClientList_t *zh_clients; - struct sockaddr_in zh_addr; /* IP addr/port of hostmanager */ - unsigned int zh_locked; /* 1 if this host is locked for - a braindump */ -} ZHostList_t; - -typedef enum _server_state { - SERV_UP, /* Server is up */ - SERV_TARDY, /* Server due for a hello */ - SERV_DEAD, /* Server is considered dead */ - SERV_STARTING /* Server is between dead and up */ -} server_state; - -typedef struct _ZNotAcked_t { - struct _ZNotAcked_t *q_forw; /* link to next */ - struct _ZNotAcked_t *q_back; /* link to prev */ - timer na_timer; /* timer for retransmit */ - long na_abstimo; /* absolute timeout to drop after */ - short na_rexmits; /* number of retransmits */ - short na_packsz; /* size of packet */ - caddr_t na_packet; /* ptr to packet */ - ZUnique_Id_t na_uid; /* uid of packet */ - union { /* address to send to */ - struct sockaddr_in na_sin; /* client address */ - int srv_idx; /* index of server */ - } dest; -#define na_addr dest.na_sin -#define na_srv_idx dest.srv_idx -} ZNotAcked_t; - -typedef struct _ZSrvPending_t { - struct _ZSrvPending_t *q_forw; /* link to next */ - struct _ZSrvPending_t *q_back; /* link to prev */ - caddr_t pend_packet; /* the notice (in pkt form) */ - short pend_len; /* len of pkt */ - unsigned int pend_auth; /* whether it is authentic */ - struct sockaddr_in pend_who; /* the addr of the sender */ -} ZSrvPending_t; - -typedef struct _ZServerDesc_t { - server_state zs_state; /* server's state */ - struct sockaddr_in zs_addr; /* server's address */ - long zs_timeout; /* Length of timeout in sec */ - timer zs_timer; /* timer struct for this server */ - struct _ZHostList_t *zs_hosts; /* pointer to list of info from this - server */ - struct _ZSrvPending_t *zs_update_queue; /* queue of packets to send - to this server when done dumping */ - short zs_numsent; /* number of hello's sent */ - unsigned int zs_dumping; /* 1 if dumping, so we should queue */ - char addr[16]; /* text version of address */ -} ZServerDesc_t; - -typedef enum ZSentType { - NOT_SENT, /* message was not xmitted */ - SENT, /* message was xmitted */ - AUTH_FAILED, /* authentication failed */ - NOT_FOUND /* user not found for uloc */ -} ZSentType; - -/* statistics gathering */ -typedef struct _ZStatistic_t { - int val; - char *str; -} ZStatistic; - -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -/* Function declarations */ - -/* found in bdump.c */ -extern void bdump_get P((ZNotice_t *notice, int auth, struct sockaddr_in *who, - ZServerDesc_t *server)); -extern void bdump_send P((void)); -extern void bdump_offer P((struct sockaddr_in *who)); -extern Code_t bdump_send_list_tcp P((ZNotice_Kind_t kind, int port, - char *class_name, char *inst, char *opcode, - char *sender, char *recip, - char **lyst, int num)); - -/* found in class.c */ -extern Code_t triplet_register P((ZClient_t *client, ZDestination *dest)); -extern Code_t triplet_deregister P((ZClient_t *client, ZDestination *dest)); -extern Code_t class_restrict P((char *z_class, ZAcl_t *acl)); -extern Code_t class_setup_restricted P((char *z_class, ZAcl_t *acl)); -extern ZClientList_t *triplet_lookup P((ZDestination *dest)); -extern ZAcl_t *class_get_acl P((ZSTRING *z_class)); -extern void class_free P((ZClientList_t *lyst)); -extern ZSTRING *class_control, *class_admin, *class_hm; -extern ZSTRING *class_ulogin, *class_ulocate; -extern void set_ZDestination_hash P((ZDestination *zd)); -extern int ZDest_eq P((ZDestination *zd1, ZDestination *zd2)); -extern int order_dest_strings P((ZDestination *zd1, ZDestination *zd2)); -extern void class_dump_subs P((register FILE *fp)); - -/* found in client.c */ -extern Code_t client_register P((ZNotice_t *notice, struct sockaddr_in *who, - register ZClient_t **client, - ZServerDesc_t *server, int wantdefaults)); -extern void client_deregister P((ZClient_t *client, ZHostList_t *host, - int flush)); -extern void client_dump_clients P((FILE *fp, ZClientList_t *clist)); -extern ZClient_t *client_which_client P((struct sockaddr_in *who, - ZNotice_t *notice)); - -/* found in common.c */ -extern char *strsave P((Zconst char *str)); -extern unsigned long hash P((Zconst char *)); -extern void subscr_quote P((char *p, FILE *fp)); - -/* found in dispatch.c */ -extern void handle_packet P((void)); -extern void clt_ack P((ZNotice_t *notice, struct sockaddr_in *who, - ZSentType sent)); -extern void nack_release P((ZClient_t *client)); -extern void sendit P((register ZNotice_t *notice, int auth, - struct sockaddr_in *who)); -extern void rexmit P((void *)); -extern void xmit P((register ZNotice_t *notice, struct sockaddr_in *dest, - int auth, ZClient_t *client)); -extern Code_t control_dispatch P((ZNotice_t *notice, int auth, - struct sockaddr_in *who, - ZServerDesc_t *server)); -extern Code_t xmit_frag P((ZNotice_t *notice, char *buf, int len, - int waitforack)); - -/* found in hostm.c */ -extern void hostm_flush P((ZHostList_t *host, ZServerDesc_t *server)); -extern void hostm_shutdown P((void)); -extern void hostm_losing P((ZClient_t *client, ZHostList_t *host)); -extern ZHostList_t *hostm_find_host P((struct in_addr *addr)); -extern ZServerDesc_t *hostm_find_server P((struct in_addr *addr)); -extern void hostm_transfer P((ZHostList_t *host, ZServerDesc_t *server)); -extern void hostm_deathgram P((struct sockaddr_in *sin, - ZServerDesc_t *server)); -extern void hostm_dump_hosts P((FILE *fp)); -extern Code_t hostm_dispatch P((ZNotice_t *notice, int auth, - struct sockaddr_in *who, ZServerDesc_t *server)); -extern void hostm_lose_ignore P((ZClient_t *client)); -extern void hostm_renumber_servers P((int *)); - -/* found in kstuff.c */ -#ifdef KERBEROS -extern int GetKerberosData P((int, struct in_addr, AUTH_DAT*, char*, char*)); -extern Code_t SendKerberosData P((int, KTEXT, char*, char*)); -#endif -void sweep_ticket_hash_table P((void *)); - -/* found in server.c */ -extern void server_timo P((void *which)); -extern void server_recover P((ZClient_t *client)), - server_dump_servers P((FILE *fp)); -extern void server_init P((void)), - server_shutdown P((void)); -extern void server_forward P((ZNotice_t *notice, int auth, - struct sockaddr_in *who)); -extern void server_kill_clt P((ZClient_t *client)); -extern void server_pending_free P((register ZSrvPending_t *pending)); -extern void server_self_queue P((ZNotice_t*, int, struct sockaddr_in *)), - server_send_queue P((ZServerDesc_t *)), - server_reset P((void)); -extern int is_server(); -extern ZServerDesc_t *server_which_server P((struct sockaddr_in *who)); -extern ZSrvPending_t *server_dequeue P((register ZServerDesc_t *server)); -extern Code_t server_dispatch P((ZNotice_t *notice, int auth, - struct sockaddr_in *who)); -extern Code_t server_adispatch P((ZNotice_t *notice, int auth, - struct sockaddr_in *who, - ZServerDesc_t *server)); - - -/* found in subscr.c */ -extern Code_t subscr_cancel P((struct sockaddr_in *sin, ZNotice_t *notice)); -extern Code_t subscr_subscribe P((ZClient_t *who, ZNotice_t *notice)), - subscr_send_subs P((ZClient_t *client, char *vers));; -extern void subscr_free_list P((ZClientList_t *list)), - subscr_cancel_client P((register ZClient_t *client)), - subscr_sendlist P((ZNotice_t *notice, int auth, struct sockaddr_in *who)); -extern void subscr_dump_subs P((FILE *fp, ZSubscr_t *subs)), - subscr_reset P((void)); -extern int compare_subs P((ZSubscr_t *s1, ZSubscr_t *s2, int do_wildcard)); -extern Code_t subscr_def_subs P((ZClient_t *who)); - -/* found in uloc.c */ -extern void uloc_hflush P((struct in_addr *addr)), - uloc_flush_client P((struct sockaddr_in *sin)), - uloc_dump_locs P((register FILE *fp)); -extern Code_t ulogin_dispatch P((ZNotice_t *notice, int auth, - struct sockaddr_in *who, ZServerDesc_t *server)), - ulocate_dispatch P((ZNotice_t *notice, int auth, struct sockaddr_in *who, - ZServerDesc_t *server)), - uloc_send_locations P((ZHostList_t *host, char *vers)); - -/* found in version.c */ -extern char *get_version P((void)); - -#undef P - - -/* global identifiers */ - -/* found in main.c */ -extern struct sockaddr_in sock_sin; /* socket descriptors */ -extern u_short hm_port; /* port # of hostmanagers */ -extern int srv_socket; /* dgram sockets for clients - and other servers */ -extern int bdump_socket; /* brain dump socket - (closed most of the time) */ - -extern fd_set interesting; /* the file descrips we are listening - to right now */ -extern int nfildes; /* number to look at in select() */ -extern int zdebug; -extern char myname[]; /* domain name of this host */ -extern ZNotAcked_t *nacklist; /* list of not ack'ed packets */ -extern Zconst char version[]; -extern u_long npackets; /* num of packets processed */ -extern long uptime; /* time we started */ -extern struct in_addr my_addr; - -/* found in bdump.c */ -extern int bdumping; /* are we dumping right now? */ - -/* found in dispatch.c */ -extern ZStatistic i_s_ctls, i_s_logins, i_s_admins, i_s_locates; -extern int num_rexmits; -extern long rexmit_secs, abs_timo; - -/* found in server.c */ -extern ZServerDesc_t *otherservers; /* array of servers */ -extern int me_server_idx; /* me (in the array of servers) */ -extern int nservers; /* number of other servers*/ - -/* found in subscr.c */ -extern ZSTRING *empty; -extern ZSTRING *wildcard_instance; - -extern struct in_addr my_addr; /* my inet address */ - -#define class_is_control(classname) (classname == class_control) -#define class_is_admin(classname) (classname == class_admin) -#define class_is_hm(classname) (classname == class_hm) -#define class_is_ulogin(classname) (classname == class_ulogin) -#define class_is_ulocate(classname) (classname == class_ulocate) - -#define ADMIN_HELLO "HELLO" /* Opcode: hello, are you there */ -#define ADMIN_IMHERE "IHEARDYOU" /* Opcode: yes, I am here */ -#define ADMIN_SHUTDOWN "GOODBYE" /* Opcode: I am shutting down */ -#define ADMIN_BDUMP "DUMP_AVAIL" /* Opcode: I will give you a dump */ -#define ADMIN_DONE "DUMP_DONE" /* Opcode: brain dump for this server - is complete */ -#define ADMIN_NEWCLT "NEXT_CLIENT" /* Opcode: this is a new client */ -#define ADMIN_LOST_CLT "LOST_CLIENT" /* Opcode: client not ack'ing */ -#define ADMIN_KILL_CLT "KILL_CLIENT" /* Opcode: client is dead, remove */ -#define ADMIN_STATUS "STATUS" /* Opcode: please send status */ - -#define ADMIN_LIMBO "LIMBO" /* Class inst: please send limbo info*/ -#define ADMIN_YOU "YOUR_STATE" /* Class inst: please send your state*/ -#define ADMIN_ME "MY_STATE" /* Class inst: please send my info */ - -#define NULLZT ((ZTriplet_t *) 0) -#define NULLZCNT ((ZClient_t *) 0) -#define NULLZCLT ((ZClientList_t *) 0) -#define NULLZST ((ZSubscr_t *) 0) -#define NULLZHLT ((ZHostList_t *) 0) -#define NULLZNAT ((ZNotAcked_t *) 0) -#define NULLZACLT ((ZAcl_t *) 0) -#define NULLZPT ((ZPacket_t *) 0) -#define NULLZSDT ((ZServerDesc_t *) 0) -#define NULLZSPT ((ZSrvPending_t *) 0) - -/* me_server_idx is the index into otherservers of this server descriptor. */ -/* the 'limbo' server is always the first server */ - -#define me_server (&otherservers[me_server_idx]) -#define limbo_server_idx() (0) -#define limbo_server (&otherservers[limbo_server_idx()]) - -#define msgs_queued() (ZQLength() || otherservers[me_server_idx].zs_update_queue) - -#define ack(a,b) clt_ack(a,b,SENT) -#define nack(a,b) clt_ack(a,b,NOT_SENT) - -#define max(a,b) ((a) > (b) ? (a) : (b)) - -#define START_CRITICAL_CODE -#define END_CRITICAL_CODE - -/* the instance that matches all instances */ -#define WILDCARD_INSTANCE "*" - -/* SERVER_SRVTAB is defined in zephyr.h */ -#define ZEPHYR_SRVTAB SERVER_SRVTAB - -#ifdef KERBEROS -#ifndef NOENCRYPTION -/* Kerberos shouldn't stick us with array types... */ -typedef struct { - des_key_schedule s; -} Sched; -#endif -#endif - -/* debugging macros */ -#ifdef DEBUG -#define zdbug(s1) if (zdebug) syslog s1; -#else /* !DEBUG */ -#define zdbug(s1) -#endif /* DEBUG */ - -#endif /* !__ZSERVER_H__ */ diff --git a/server/zserver.h.old b/server/zserver.h.old deleted file mode 100644 index 7b51ac1..0000000 --- a/server/zserver.h.old +++ /dev/null @@ -1,424 +0,0 @@ -#ifndef __ZSERVER_H__ -#define __ZSERVER_H__ -/* This file is part of the Project Athena Zephyr Notification System. - * It contains declarations for use in the server. - * - * Created by: John T. Kohl - * - * $Source$ - * $Author$ - * $Zephyr: /mit/zephyr/src/server/RCS/zserver.h,v 1.34 91/03/08 12:53:24 raeburn Exp $ - * - * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology. - * For copying and distribution information, see the file - * "mit-copyright.h". - */ - -#include <zephyr/mit-copyright.h> - -#include <zephyr/zephyr.h> /* which includes <errno.h>, - <sys/types.h>, - <netinet/in.h>, - <sys/time.h>, - <stdio.h>, - <krb.h> */ -#include <arpa/inet.h> -#include <zephyr/acl.h> -#include <sys/file.h> -#include <fcntl.h> - -#include <zephyr/zsyslog.h> - -#include <strings.h> -#include <signal.h> -#ifdef lint -#include <sys/uio.h> /* so it shuts up about struct iovec */ -#endif /* lint */ -#ifdef _IBMR2 -#include <sys/select.h> -#endif -#include "zsrv_err.h" - -#include "timer.h" -#include "zsrv_conf.h" /* configuration params */ - -#include "zstring.h" -#include "access.h" -#include "unix.h" -#include "zalloc.h" - -/* definitions for the Zephyr server */ - -/* structures */ - -/* - * ZDestination: Where is this notice going to? This includes class, - * instance, and recipient at the moment. - */ - -typedef struct _ZDestination { - unsigned long hash_value; - ZSTRING *classname; - ZSTRING *inst; - ZSTRING *recip; -} ZDestination; - -/* typedef struct _Notice { - ZNotice_t *notice; - struct _ZDestination dest; - ZSTRING *sender; - int msg_no; -} Notice; -*/ -typedef struct _ZSubscr_t { - struct _ZSubscr_t *q_forw; /* links in client's subscr. queue */ - struct _ZSubscr_t *q_back; - struct _ZDestination zst_dest; /* destination of messages */ -} ZSubscr_t; - -typedef struct _ZClient_t { - struct sockaddr_in zct_sin; /* ipaddr/port of client */ - struct _ZSubscr_t *zct_subs; /* subscriptions */ -#ifdef KERBEROS - C_Block zct_cblock; /* session key for this client */ -#endif /* KERBEROS */ - ZSTRING *zct_principal; /* krb principal of user */ - long last_msg; /* last message sent to this client */ - long last_check; /* actually, last time the other - server was asked to check... */ -} ZClient_t; - -typedef struct _ZClientList_t { - struct _ZClientList_t *q_forw; - struct _ZClientList_t *q_back; - struct _ZClient_t *zclt_client; -} ZClientList_t; - -typedef struct _ZClass_t { - struct _ZClass_t *q_forw; - struct _ZClass_t *q_back; - ZDestination zct_dest; - ZAcl_t *zct_acl; - ZClientList_t *zct_clientlist; -} ZClass_t; - -typedef struct _ZHostList_t { - struct _ZHostList_t *q_forw; - struct _ZHostList_t *q_back; - ZClientList_t *zh_clients; - struct sockaddr_in zh_addr; /* IP addr/port of hostmanager */ - unsigned int zh_locked; /* 1 if this host is locked for - a braindump */ -} ZHostList_t; - -typedef enum _server_state { - SERV_UP, /* Server is up */ - SERV_TARDY, /* Server due for a hello */ - SERV_DEAD, /* Server is considered dead */ - SERV_STARTING /* Server is between dead and up */ -} server_state; - -typedef struct _ZNotAcked_t { - struct _ZNotAcked_t *q_forw; /* link to next */ - struct _ZNotAcked_t *q_back; /* link to prev */ - timer na_timer; /* timer for retransmit */ - long na_abstimo; /* absolute timeout to drop after */ - short na_rexmits; /* number of retransmits */ - short na_packsz; /* size of packet */ - caddr_t na_packet; /* ptr to packet */ - ZUnique_Id_t na_uid; /* uid of packet */ - union { /* address to send to */ - struct sockaddr_in na_sin; /* client address */ - int srv_idx; /* index of server */ - } dest; -#define na_addr dest.na_sin -#define na_srv_idx dest.srv_idx -} ZNotAcked_t; - -typedef struct _ZSrvPending_t { - struct _ZSrvPending_t *q_forw; /* link to next */ - struct _ZSrvPending_t *q_back; /* link to prev */ - caddr_t pend_packet; /* the notice (in pkt form) */ - short pend_len; /* len of pkt */ - unsigned int pend_auth; /* whether it is authentic */ - struct sockaddr_in pend_who; /* the addr of the sender */ -} ZSrvPending_t; - -typedef struct _ZServerDesc_t { - server_state zs_state; /* server's state */ - struct sockaddr_in zs_addr; /* server's address */ - long zs_timeout; /* Length of timeout in sec */ - timer zs_timer; /* timer struct for this server */ - struct _ZHostList_t *zs_hosts; /* pointer to list of info from this - server */ - struct _ZSrvPending_t *zs_update_queue; /* queue of packets to send - to this server when done dumping */ - short zs_numsent; /* number of hello's sent */ - unsigned int zs_dumping; /* 1 if dumping, so we should queue */ - char addr[16]; /* text version of address */ -} ZServerDesc_t; - -typedef enum ZSentType { - NOT_SENT, /* message was not xmitted */ - SENT, /* message was xmitted */ - AUTH_FAILED, /* authentication failed */ - NOT_FOUND /* user not found for uloc */ -} ZSentType; - -/* statistics gathering */ -typedef struct _ZStatistic_t { - int val; - char *str; -} ZStatistic; - -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -/* Function declarations */ - -/* found in bdump.c */ -extern void bdump_get P((ZNotice_t *notice, int auth, struct sockaddr_in *who, - ZServerDesc_t *server)); -extern void bdump_send P((void)); -extern void bdump_offer P((struct sockaddr_in *who)); -extern Code_t bdump_send_list_tcp P((ZNotice_Kind_t kind, int port, - char *class_name, char *inst, char *opcode, - char *sender, char *recip, - char **lyst, int num)); - -/* found in class.c */ -extern Code_t class_register P((ZClient_t *client, ZSubscr_t *subs)); -extern Code_t class_deregister P((ZClient_t *client, ZSubscr_t *subs)); -extern Code_t class_restrict P((char *z_class, ZAcl_t *acl)); -extern Code_t class_setup_restricted P((char *z_class, ZAcl_t *acl)); -extern ZClientList_t *class_lookup P((ZSubscr_t *subs)); -extern ZAcl_t *class_get_acl P((ZSTRING *z_class)); -extern void class_free P((ZClientList_t *lyst)); -extern ZSTRING *class_control, *class_admin, *class_hm; -extern ZSTRING *class_ulogin, *class_ulocate; -extern void set_ZDestination_hash P((ZDestination *zd)); -extern int ZDest_eq P((ZDestination *zd1, ZDestination *zd2)); -extern int order_dest_strings P((ZDestination *zd1, ZDestination *zd2)); - -/* found in client.c */ -extern Code_t client_register P((ZNotice_t *notice, struct sockaddr_in *who, - register ZClient_t **client, - ZServerDesc_t *server, int wantdefaults)); -extern void client_deregister P((ZClient_t *client, ZHostList_t *host, - int flush)); -extern void client_dump_clients P((FILE *fp, ZClientList_t *clist)); -extern ZClient_t *client_which_client P((struct sockaddr_in *who, - ZNotice_t *notice)); - -/* found in common.c */ -extern char *strsave P((Zconst char *str)); -extern unsigned long hash P((Zconst char *)); - -/* found in dispatch.c */ -extern void handle_packet P((void)); -extern void clt_ack P((ZNotice_t *notice, struct sockaddr_in *who, - ZSentType sent)); -extern void nack_release P((ZClient_t *client)); -extern void sendit P((register ZNotice_t *notice, int auth, - struct sockaddr_in *who)); -extern void rexmit P((void *)); -extern void xmit P((register ZNotice_t *notice, struct sockaddr_in *dest, - int auth, ZClient_t *client)); -extern Code_t control_dispatch P((ZNotice_t *notice, int auth, - struct sockaddr_in *who, - ZServerDesc_t *server)); -extern Code_t xmit_frag P((ZNotice_t *notice, char *buf, int len, - int waitforack)); - -/* found in hostm.c */ -extern void hostm_flush P((ZHostList_t *host, ZServerDesc_t *server)); -extern void hostm_shutdown P((void)); -extern void hostm_losing P((ZClient_t *client, ZHostList_t *host)); -extern ZHostList_t *hostm_find_host P((struct in_addr *addr)); -extern ZServerDesc_t *hostm_find_server P((struct in_addr *addr)); -extern void hostm_transfer P((ZHostList_t *host, ZServerDesc_t *server)); -extern void hostm_deathgram P((struct sockaddr_in *sin, - ZServerDesc_t *server)); -extern void hostm_dump_hosts P((FILE *fp)); -extern Code_t hostm_dispatch P((ZNotice_t *notice, int auth, - struct sockaddr_in *who, ZServerDesc_t *server)); -extern void hostm_lose_ignore P((ZClient_t *client)); -extern void hostm_renumber_servers P((int *)); - -/* found in kstuff.c */ -#ifdef KERBEROS -extern int GetKerberosData P((int, struct in_addr, AUTH_DAT*, char*, char*)); -extern Code_t SendKerberosData P((int, KTEXT, char*, char*)); -#endif - -/* found in server.c */ -extern void server_timo P((void *which)); -extern void server_recover P((ZClient_t *client)), - server_dump_servers P((FILE *fp)); -extern void server_init P((void)), - server_shutdown P((void)); -extern void server_forward P((ZNotice_t *notice, int auth, - struct sockaddr_in *who)); -extern void server_kill_clt P((ZClient_t *client)); -extern void server_pending_free P((register ZSrvPending_t *pending)); -extern void server_self_queue P((ZNotice_t*, int, struct sockaddr_in *)), - server_send_queue P((ZServerDesc_t *)), - server_reset P((void)); -extern int is_server(); -extern ZServerDesc_t *server_which_server P((struct sockaddr_in *who)); -extern ZSrvPending_t *server_dequeue P((register ZServerDesc_t *server)); -extern Code_t server_dispatch P((ZNotice_t *notice, int auth, - struct sockaddr_in *who)); -extern Code_t server_adispatch P((ZNotice_t *notice, int auth, - struct sockaddr_in *who, - ZServerDesc_t *server)); - - -/* found in subscr.c */ -extern Code_t subscr_cancel P((struct sockaddr_in *sin, ZNotice_t *notice)); -extern Code_t subscr_subscribe P((ZClient_t *who, ZNotice_t *notice)), - subscr_send_subs P((ZClient_t *client, char *vers));; -extern ZClientList_t *subscr_match_list P((ZNotice_t *notice)); -extern void subscr_free_list P((ZClientList_t *list)), - subscr_cancel_client P((register ZClient_t *client)), - subscr_sendlist P((ZNotice_t *notice, int auth, struct sockaddr_in *who)); -extern void subscr_dump_subs P((FILE *fp, ZSubscr_t *subs)), - subscr_reset P((void)); -extern int compare_subs P((ZSubscr_t *s1, ZSubscr_t *s2, int do_wildcard)); -extern Code_t subscr_def_subs P((ZClient_t *who)); - -/* found in uloc.c */ -extern void uloc_hflush P((struct in_addr *addr)), - uloc_flush_client P((struct sockaddr_in *sin)), - uloc_dump_locs P((register FILE *fp)); -extern Code_t ulogin_dispatch P((ZNotice_t *notice, int auth, - struct sockaddr_in *who, ZServerDesc_t *server)), - ulocate_dispatch P((ZNotice_t *notice, int auth, struct sockaddr_in *who, - ZServerDesc_t *server)), - uloc_send_locations P((ZHostList_t *host, char *vers)); - -/* found in version.c */ -extern char *get_version P((void)); - -#undef P - - -/* global identifiers */ - -/* found in main.c */ -extern struct sockaddr_in sock_sin; /* socket descriptors */ -extern u_short hm_port; /* port # of hostmanagers */ -extern int srv_socket; /* dgram sockets for clients - and other servers */ -extern int bdump_socket; /* brain dump socket - (closed most of the time) */ - -extern fd_set interesting; /* the file descrips we are listening - to right now */ -extern int nfildes; /* number to look at in select() */ -extern int zdebug; -extern char myname[]; /* domain name of this host */ -extern ZNotAcked_t *nacklist; /* list of not ack'ed packets */ -extern Zconst char version[]; -extern u_long npackets; /* num of packets processed */ -extern long uptime; /* time we started */ -extern struct in_addr my_addr; - -/* found in bdump.c */ -extern int bdumping; /* are we dumping right now? */ - -/* found in dispatch.c */ -extern ZStatistic i_s_ctls, i_s_logins, i_s_admins, i_s_locates; -extern int num_rexmits; -extern long rexmit_secs, abs_timo; - -/* found in server.c */ -extern ZServerDesc_t *otherservers; /* array of servers */ -extern int me_server_idx; /* me (in the array of servers) */ -extern int nservers; /* number of other servers*/ - -/* found in subscr.c */ -extern ZSTRING *empty; -extern ZSTRING *wildcard_instance; -extern ZSTRING *wildcard_class; -extern ZSubscr_t matchall_sub; - -extern struct in_addr my_addr; /* my inet address */ - -#define class_is_control(classname) (classname == class_control) -#define class_is_admin(classname) (classname == class_admin) -#define class_is_hm(classname) (classname == class_hm) -#define class_is_ulogin(classname) (classname == class_ulogin) -#define class_is_ulocate(classname) (classname == class_ulocate) - -#define ADMIN_HELLO "HELLO" /* Opcode: hello, are you there */ -#define ADMIN_IMHERE "IHEARDYOU" /* Opcode: yes, I am here */ -#define ADMIN_SHUTDOWN "GOODBYE" /* Opcode: I am shutting down */ -#define ADMIN_BDUMP "DUMP_AVAIL" /* Opcode: I will give you a dump */ -#define ADMIN_DONE "DUMP_DONE" /* Opcode: brain dump for this server - is complete */ -#define ADMIN_NEWCLT "NEXT_CLIENT" /* Opcode: this is a new client */ -#define ADMIN_LOST_CLT "LOST_CLIENT" /* Opcode: client not ack'ing */ -#define ADMIN_KILL_CLT "KILL_CLIENT" /* Opcode: client is dead, remove */ -#define ADMIN_STATUS "STATUS" /* Opcode: please send status */ - -#define ADMIN_LIMBO "LIMBO" /* Class inst: please send limbo info*/ -#define ADMIN_YOU "YOUR_STATE" /* Class inst: please send your state*/ -#define ADMIN_ME "MY_STATE" /* Class inst: please send my info */ - -#define NULLZCT ((ZClass_t *) 0) -#define NULLZCNT ((ZClient_t *) 0) -#define NULLZCLT ((ZClientList_t *) 0) -#define NULLZST ((ZSubscr_t *) 0) -#define NULLZHLT ((ZHostList_t *) 0) -#define NULLZNAT ((ZNotAcked_t *) 0) -#define NULLZACLT ((ZAcl_t *) 0) -#define NULLZPT ((ZPacket_t *) 0) -#define NULLZSDT ((ZServerDesc_t *) 0) -#define NULLZSPT ((ZSrvPending_t *) 0) - -/* me_server_idx is the index into otherservers of this server descriptor. */ -/* the 'limbo' server is always the first server */ - -#define me_server (&otherservers[me_server_idx]) -#define limbo_server_idx() (0) -#define limbo_server (&otherservers[limbo_server_idx()]) - -#define msgs_queued() (ZQLength() || otherservers[me_server_idx].zs_update_queue) - -#define ack(a,b) clt_ack(a,b,SENT) -#define nack(a,b) clt_ack(a,b,NOT_SENT) - -#define max(a,b) ((a) > (b) ? (a) : (b)) - -#define START_CRITICAL_CODE -#define END_CRITICAL_CODE - -/* the magic class to match all packets */ -#define MATCHALL_CLASS "zmatch_all" -/* the instance that matches all instances */ -#define WILDCARD_INSTANCE "*" - -/* SERVER_SRVTAB is defined in zephyr.h */ -#define ZEPHYR_SRVTAB SERVER_SRVTAB - -#ifdef KERBEROS -#ifndef NOENCRYPTION -/* Kerberos shouldn't stick us with array types... */ -typedef struct { - des_key_schedule s; -} Sched; -#endif -#endif - -/* debugging macros */ -#ifdef DEBUG -#define zdbug(s1) if (zdebug) syslog s1; -#else /* !DEBUG */ -#define zdbug(s1) -#endif /* DEBUG */ - -#endif /* !__ZSERVER_H__ */ diff --git a/server/zsrv_conf.h b/server/zsrv_conf.h index cb81883..2440d1d 100644 --- a/server/zsrv_conf.h +++ b/server/zsrv_conf.h @@ -16,32 +16,22 @@ #define __ZSRV_CONF_H__ #include <zephyr/mit-copyright.h> -/* Magic path names */ -#ifndef HESIOD -#define SERVER_LIST_FILE "/etc/athena/zephyr/server.list" -#endif +/* Path names are relative to CONFDIR, except for the class registry. */ -/* ACL's for pre-registered classes */ -/* Directory containing acls and other info */ -#ifndef ZEPHYR_ACL_DIR -#define ZEPHYR_ACL_DIR "/etc/athena/zephyr/acl/" +#ifndef ZEPHYR_USES_HESIOD +#define SERVER_LIST_FILE "server.list" +#endif +#define REALM_LIST_FILE "realm.list" +#ifdef ZEPHYR_USES_KERBEROS +#define ZEPHYR_SRVTAB "srvtab" +#define ZEPHYR_TKFILE "ztkts" #endif -/* name of the class registry */ +#define ZEPHYR_ACL_DIR "acl/" #define ZEPHYR_CLASS_REGISTRY "class-registry.acl" +#define DEFAULT_SUBS_FILE "default.subscriptions" -#ifdef KERBEROS -/* name of file to hold the tickets for keys to exchange with other servers */ -#define ZEPHYR_TKFILE "/etc/athena/zephyr/ztkts" - -/* The pathname of the Kerberos srvtab file is defined in zephyr_conf.h. */ -#endif /* KERBEROS */ - -/* default subscription file */ -#define DEFAULT_SUBS_FILE "/etc/athena/zephyr/default.subscriptions" - -/* client defines */ -#define REXMIT_SECS ((long) 20) /* rexmit delay on normal notices */ -#define NUM_REXMITS (9) /* number of rexmits */ +#define REXMIT_TIMES { 2, 2, 4, 4, 8, 8, 16, 32, 64, 128, 256, 512, -1 } +#define NUM_REXMIT_TIMES 12 /* hostmanager defines */ #define LOSE_TIMO (60) /* time during which a losing host @@ -56,4 +46,8 @@ when tardy */ #define H_NUM_STARTING 2 /* num hello's before going dead when starting */ + +#define SWEEP_INTERVAL 3600 /* Time between sweeps of the ticket + hash table */ + #endif /* __ZSRV_CONF_H__ */ diff --git a/server/zsrv_conf.h.auth b/server/zsrv_conf.h.auth deleted file mode 100644 index 6057130..0000000 --- a/server/zsrv_conf.h.auth +++ /dev/null @@ -1,63 +0,0 @@ -/* This file is part of the Project Athena Zephyr Notification System. - * It contains site-specific definitions for use in the server. - * - * Created by: John T. Kohl - * - * $Source$ - * $Author$ - * $Header$ - * - * Copyright (c) 1988 by the Massachusetts Institute of Technology. - * For copying and distribution information, see the file - * "mit-copyright.h". - */ - -#ifndef __ZSRV_CONF_H__ -#define __ZSRV_CONF_H__ -#include <zephyr/mit-copyright.h> - -/* Magic path names */ -#ifndef HESIOD -#define SERVER_LIST_FILE "/etc/athena/zephyr/server.list" -#endif - -/* ACL's for pre-registered classes */ -/* Directory containing acls and other info */ -#ifndef ZEPHYR_ACL_DIR -#define ZEPHYR_ACL_DIR "/etc/athena/zephyr/acl/" -#endif -/* name of the class registry */ -#define ZEPHYR_CLASS_REGISTRY "class-registry.acl" - -#ifdef KERBEROS -/* name of file to hold the tickets for keys to exchange with other servers */ -#define ZEPHYR_TKFILE "/etc/athena/zephyr/ztkts" - -/* The pathname of the Kerberos srvtab file is defined in zephyr_conf.h. */ -#endif /* KERBEROS */ - -/* default subscription file */ -#define DEFAULT_SUBS_FILE "/etc/athena/zephyr/default.subscriptions" - -/* client defines */ -#define REXMIT_SECS ((long) 20) /* rexmit delay on normal notices */ -#define NUM_REXMITS (9) /* number of rexmits */ - -/* hostmanager defines */ -#define LOSE_TIMO (60) /* time during which a losing host - must respond to a ping */ - -/* server-server defines */ -#define TIMO_UP ((long) 60) /* timeout between up and tardy */ -#define TIMO_TARDY ((long) 120) /* timeout btw tardy hellos */ -#define TIMO_DEAD ((long)(15*60)) /* timeout between hello's for dead */ - -#define H_NUM_TARDY 5 /* num hello's before going dead - when tardy */ -#define H_NUM_STARTING 2 /* num hello's before going dead - when starting */ - -#define SWEEP_INTERVAL 3600 /* Time between sweeps of the ticket - hash table */ - -#endif /* __ZSRV_CONF_H__ */ diff --git a/server/zsrv_err.et b/server/zsrv_err.et index 26bbc0d..d3b9eab 100644 --- a/server/zsrv_err.et +++ b/server/zsrv_err.et @@ -38,4 +38,8 @@ ec ZSRV_RCSID, "$Id$" ec ZSRV_BADSUBPORT, "Illegal port specified in subscription" +ec ZSRV_NORLM, + "No such realm" +ec ZSRV_EMPTYCLASS, + "Class is now empty" end diff --git a/server/zstring.c b/server/zstring.c index 6b5aed3..955e0b8 100644 --- a/server/zstring.c +++ b/server/zstring.c @@ -12,177 +12,156 @@ */ #include <zephyr/mit-copyright.h> +#include "zserver.h" #ifndef lint #ifndef SABER -static char rcsid_zstring_c[] = - "$Id$"; +static const char rcsid_zstring_c[] = +"$Id$"; #endif #endif -#include <mit-copyright.h> +static String *zhash[STRING_HASH_TABLE_SIZE]; -#include <ctype.h> -#if defined(__STDC__) && !defined(__HIGHC__) && !defined(SABER) -#include <stdlib.h> -#endif -#include <string.h> - -#include <zephyr/zephyr.h> -#include "zstring.h" - -static ZSTRING *zhash[ZSTRING_HASH_TABLE_SIZE]; - -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -extern unsigned long hash P((Zconst char *s)); -extern char *strsave P((Zconst char *s)); -#undef P - -ZSTRING * -make_zstring(s, downcase) - char *s; - int downcase; +String * +make_string(s, downcase) + char *s; + int downcase; { - char *new_s,*p; - ZSTRING *new_z,*hp; - int i; - - if (downcase) { - new_s = strsave(s); - p = new_s; - while(*p) { - if (isascii(*p) && isupper(*p)) - *p = tolower(*p); - p++; + char *new_s,*p; + String *new_z,*hp; + int i; + + if (downcase) { + new_s = strsave(s); + p = new_s; + while(*p) { + if (isascii(*p) && isupper(*p)) + *p = tolower(*p); + p++; + } + } else { + new_s = s; } - } else { - new_s = s; - } - new_z = find_zstring(new_s,0); - if (new_z != NULL) { - if (downcase) - free(new_s); - new_z->ref_count++; - return(new_z); - } - - /* Initialize new ZSTRING */ - - if (!downcase) - new_s = strsave(s); - new_z = (ZSTRING *) malloc(sizeof(ZSTRING)); - new_z->string = new_s; - new_z->ref_count = 1; + new_z = find_string(new_s,0); + if (new_z != NULL) { + if (downcase) + free(new_s); + new_z->ref_count++; + return(new_z); + } + + /* Initialize new String */ + + if (!downcase) + new_s = strsave(s); + new_z = (String *) malloc(sizeof(String)); + new_z->string = new_s; + new_z->ref_count = 1; - /* Add to beginning of hash table */ - new_z->hash_val = hash(new_s); - i = new_z->hash_val % ZSTRING_HASH_TABLE_SIZE; - hp = zhash[i]; - new_z->next = hp; - if (hp != NULL) - hp->prev = new_z; - new_z->prev = NULL; - zhash[i] = new_z; - - return(new_z); + /* Add to beginning of hash table */ + new_z->hash_val = hash(new_s); + i = new_z->hash_val % STRING_HASH_TABLE_SIZE; + hp = zhash[i]; + new_z->next = hp; + if (hp != NULL) + hp->prev = new_z; + new_z->prev = NULL; + zhash[i] = new_z; + + return new_z; } void -free_zstring(z) - ZSTRING *z; +free_string(z) + String *z; { - if (z == (ZSTRING *) NULL) - return; - - z->ref_count--; - if (z->ref_count > 0) - return; - - /* delete zstring completely */ - if(z->prev == NULL) - zhash[hash(z->string) % ZSTRING_HASH_TABLE_SIZE] = z->next; - else - z->prev->next = z->next; + if (z == (String *) NULL) + return; + + z->ref_count--; + if (z->ref_count > 0) + return; + + /* delete string completely */ + if(z->prev == NULL) + zhash[hash(z->string) % STRING_HASH_TABLE_SIZE] = z->next; + else + z->prev->next = z->next; - if (z->next != NULL) - z->next->prev = z->prev; + if (z->next != NULL) + z->next->prev = z->prev; - free(z->string); - free(z); - return; + free(z->string); + free(z); } -ZSTRING * -find_zstring(s,downcase) - char *s; - int downcase; +String * +find_string(s,downcase) + char *s; + int downcase; { - char *new_s,*p; - ZSTRING *z; - - if (downcase) { - new_s = strsave(s); - p = new_s; - while (*p) { - if (isascii(*p) && isupper(*p)) - *p = tolower(*p); - p++; + char *new_s,*p; + String *z; + + if (downcase) { + new_s = strsave(s); + p = new_s; + while (*p) { + if (isascii(*p) && isupper(*p)) + *p = tolower(*p); + p++; + } + } else { + new_s = s; } - } else { - new_s = s; - } - z = zhash[hash(new_s) % ZSTRING_HASH_TABLE_SIZE]; - while (z != (ZSTRING *)NULL) { - if (strcmp(new_s,z->string) == 0) - break; - z = z->next; - } + z = zhash[hash(new_s) % STRING_HASH_TABLE_SIZE]; + while (z != NULL) { + if (strcmp(new_s, z->string) == 0) + break; + z = z->next; + } - if (downcase) - free(new_s); + if (downcase) + free(new_s); - return(z); + return z; } int -comp_zstring(a,b) - ZSTRING *a, *b; +comp_string(a,b) + String *a, *b; { - if (a->hash_val > b->hash_val) - return(1); - if (a->hash_val < b->hash_val) - return(-1); - return(strcmp(a->string,b->string)); + if (a->hash_val > b->hash_val) + return 1; + if (a->hash_val < b->hash_val) + return -1; + return strcmp(a->string,b->string); } void -print_zstring_table(f) - FILE *f; +print_string_table(f) + FILE *f; { - ZSTRING *p; - int i; - - for(i=0;i<ZSTRING_HASH_TABLE_SIZE;i++) { - p = zhash[i]; - while (p != (ZSTRING *) NULL) { - fprintf(f,"[%d] %s\n",p->ref_count,p->string); - p = p->next; + String *p; + int i; + + for(i = 0; i < STRING_HASH_TABLE_SIZE; i++) { + p = zhash[i]; + while (p != (String *) NULL) { + fprintf(f,"[%d] %s\n",p->ref_count,p->string); + p = p->next; + } } - } - return; } -ZSTRING * -dup_zstring(z) - ZSTRING *z; +String * +dup_string(z) + String *z; { - z->ref_count++; - return(z); + z->ref_count++; + return z; } + diff --git a/server/zstring.h b/server/zstring.h index 5d3aaa1..eb3a3da 100644 --- a/server/zstring.h +++ b/server/zstring.h @@ -12,33 +12,24 @@ #ifndef __zstring_h #define __zstring_h __FILE__ -#define ZSTRING_HASH_TABLE_SIZE 1024 +#define STRING_HASH_TABLE_SIZE 1024 #include <stdio.h> -typedef struct _zstring +typedef struct _String { - char *string; /* the string itself */ - int ref_count; /* for gc */ - unsigned long hash_val; /* hash value for this string */ - struct _zstring *next; /* for linking in hash table */ - struct _zstring *prev; /* for linking in hash table */ -} ZSTRING; - -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -ZSTRING *make_zstring P((char *s, int downcase)); -void free_zstring P((ZSTRING *z)); -ZSTRING *find_zstring P((char *s, int downcase)); -ZSTRING *dup_zstring P((ZSTRING *z)); -int comp_zstring P((ZSTRING *a, ZSTRING *b)); -void print_zstring_table P((FILE *f)); - -#undef P - + char *string; /* the string itself */ + int ref_count; /* for gc */ + unsigned long hash_val; /* hash value for this string */ + struct _String *next, *prev; /* for linking in hash table */ +} String; + +String *make_string __P((char *s, int downcase)); +void free_string __P((String *z)); +String *find_string __P((char *s, int downcase)); +String *dup_string __P((String *z)); +int comp_string __P((String *a, String *b)); +void print_string_table __P((FILE *f)); #endif /* __zstring_h */ + |