summaryrefslogtreecommitdiffstats
path: root/usr.sbin/xntpd/xntpres/xntpres.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/xntpd/xntpres/xntpres.c')
-rw-r--r--usr.sbin/xntpd/xntpres/xntpres.c850
1 files changed, 0 insertions, 850 deletions
diff --git a/usr.sbin/xntpd/xntpres/xntpres.c b/usr.sbin/xntpd/xntpres/xntpres.c
deleted file mode 100644
index 47c6eda..0000000
--- a/usr.sbin/xntpd/xntpres/xntpres.c
+++ /dev/null
@@ -1,850 +0,0 @@
-/* xntpres.c,v 3.1 1993/07/06 01:12:09 jbj Exp
- * xntpres - process configuration entries which require use of the resolver
- *
- * This is meant to be run by xntpd on the fly. It is not guaranteed
- * to work properly if run by hand. This is actually a quick hack to
- * stave off violence from people who hate using numbers in the
- * configuration file (at least I hope the rest of the daemon is
- * better than this). Also might provide some ideas about how one
- * might go about autoconfiguring an NTP distribution network.
- *
- * Usage is:
- * xntpres [-d] [-r] keyid keyfile configuration_data
- */
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <netdb.h>
-#include <signal.h>
-#include <errno.h>
-
-#include "ntp_select.h"
-#include "ntp_fp.h"
-#include "ntp.h"
-#include "ntp_io.h"
-#include "ntp_malloc.h"
-#include "ntp_request.h"
-#include "ntp_string.h"
-#include "ntp_stdlib.h"
-#include "ntp_syslog.h"
-
-#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
-
-/*
- * Each item we are to resolve and configure gets one of these
- * structures defined for it.
- */
-struct conf_entry {
- struct conf_entry *ce_next;
- char *ce_name; /* name we are trying to resolve */
- struct conf_peer ce_config; /* configuration info for peer */
-};
-#define ce_peeraddr ce_config.peeraddr
-#define ce_hmode ce_config.hmode
-#define ce_version ce_config.version
-#define ce_minpoll ce_config.minpoll
-#define ce_maxpoll ce_config.maxpoll
-#define ce_flags ce_config.flags
-#define ce_ttl ce_config.ttl
-#define ce_keyid ce_config.keyid
-
-/*
- * confentries is a pointer to the list of configuration entries
- * we have left to do.
- */
-struct conf_entry *confentries = NULL;
-
-/*
- * We take an interrupt every thirty seconds, at which time we decrement
- * config_timer and resolve_timer. The former is set to 2, so we retry
- * unsucessful reconfigurations every minute. The latter is set to
- * an exponentially increasing value which starts at 2 and increases to
- * 32. When this expires we retry failed name resolutions.
- *
- * We sleep SLEEPTIME seconds before doing anything, to give the server
- * time to arrange itself.
- */
-#define MINRESOLVE 2
-#define MAXRESOLVE 32
-#define CONFIG_TIME 2
-#define ALARM_TIME 30
-
-#define SLEEPTIME 2
-
-int config_timer = 0;
-int resolve_timer = 0;
-
-int resolve_value; /* next value of resolve timer */
-
-/*
- * Big hack attack
- */
-#define LOCALHOST 0x7f000001 /* 127.0.0.1, in hex, of course */
-#define SKEWTIME 0x08000000 /* 0.03125 seconds as a l_fp fraction */
-
-/*
- * Select time out. Set to 2 seconds. The server is on the local machine,
- * after all.
- */
-#define TIMEOUT_SEC 2
-#define TIMEOUT_USEC 0
-
-
-/*
- * Input processing. The data on each line in the configuration file
- * is supposed to consist of entries in the following order
- */
-#define TOK_HOSTNAME 0
-#define TOK_HMODE 1
-#define TOK_VERSION 2
-#define TOK_MINPOLL 3
-#define TOK_MAXPOLL 4
-#define TOK_FLAGS 5
-#define TOK_TTL 6
-#define TOK_KEYID 7
-#define NUMTOK 8
-
-#define MAXLINESIZE 512
-
-
-/*
- * File descriptor for ntp request code.
- */
-int sockfd = -1;
-
-/*
- * Misc. data from argument processing
- */
-int removefile = 0; /* remove configuration file when done */
-
-U_LONG req_keyid; /* request keyid */
-char *keyfile; /* file where keys are kept */
-char *conffile; /* name of the file with configuration info */
-
-char *progname;
-int debug = 0;
-extern char *Version;
-extern int errno;
-
-static RETSIGTYPE bong P((int));
-static void checkparent P((void));
-static void removeentry P((struct conf_entry *));
-static void addentry P((char *, int, int, int, int, int, int, U_LONG));
-static int findhostaddr P((struct conf_entry *));
-static void openntp P((void));
-static int request P((struct conf_peer *));
-static char * nexttoken P((char **));
-static void readconf P((FILE *, char *));
-static void doconfigure P((int));
-
-/*
- * main - parse arguments and handle options
- */
-void
-main(argc, argv)
- int argc;
- char *argv[];
-{
- int c;
- int errflg = 0;
- char *cp;
- FILE *in;
- extern int ntp_optind;
-
- progname = argv[0];
-
- /*
- * Better get syslog open early since stderr messages are likely
- * ending up in the twilight zone
- */
- cp = strrchr(argv[0], '/');
- if (cp == 0)
- cp = argv[0];
- else
- cp++;
-
-#ifndef LOG_DAEMON
- openlog(cp, LOG_PID);
-#else
-
-#ifndef LOG_NTP
-#define LOG_NTP LOG_DAEMON
-#endif
- openlog(cp, LOG_PID | LOG_NDELAY, LOG_NTP);
-#ifdef DEBUG
- if (debug)
- setlogmask(LOG_UPTO(LOG_DEBUG));
- else
-#endif /* DEBUG */
- setlogmask(LOG_UPTO(LOG_INFO));
-#endif /* LOG_DAEMON */
-
- syslog(LOG_NOTICE, Version);
-
- while ((c = ntp_getopt(argc, argv, "dr")) != EOF)
- switch (c) {
- case 'd':
- ++debug;
- break;
- case 'r':
- ++removefile;
- break;
- default:
- errflg++;
- break;
- }
- if (errflg || (ntp_optind + 3) != argc) {
- (void) fprintf(stderr,
- "usage: %s [-d] [-r] keyid keyfile conffile\n", progname);
- syslog(LOG_ERR, "exiting due to usage error");
- exit(2);
- }
-
- if (!atouint(argv[ntp_optind], &req_keyid)) {
- syslog(LOG_ERR, "undecodeable keyid %s", argv[ntp_optind]);
- exit(1);
- }
-
- keyfile = argv[ntp_optind+1];
- conffile = argv[ntp_optind+2];
-
- /*
- * Make sure we have the key we need
- */
- if (!authreadkeys(keyfile))
- exit(1);
- if (!authhavekey(req_keyid)) {
- syslog(LOG_ERR, "request keyid %lu not found in %s",
- req_keyid, keyfile);
- exit(1);
- }
-
- /*
- * Read the configuration info
- */
- if ((in = fopen(conffile, "r")) == NULL) {
- syslog(LOG_ERR, "can't open configuration file %s: %m",
- conffile);
- exit(1);
- }
- readconf(in, conffile);
- (void) fclose(in);
- if (removefile)
- (void) unlink(conffile);
-
- /*
- * Sleep a little to make sure the server is completely up
- */
- sleep(SLEEPTIME);
-
- /*
- * Make a first cut at resolving the bunch
- */
- doconfigure(1);
- if (confentries == NULL)
- exit(0); /* done that quick */
-
- /*
- * Here we've got some problem children. Set up the timer
- * and wait for it.
- */
- resolve_value = resolve_timer = MINRESOLVE;
- config_timer = CONFIG_TIME;
- (void) signal(SIGALRM, bong);
- alarm(ALARM_TIME);
-
- for (;;) {
- if (confentries == NULL)
- exit(0);
- checkparent();
- if (resolve_timer == 0) {
- if (resolve_value < MAXRESOLVE)
- resolve_value <<= 1;
- resolve_timer = resolve_value;
- config_timer = CONFIG_TIME;
- doconfigure(1);
- continue;
- } else if (config_timer == 0) {
- config_timer = CONFIG_TIME;
- doconfigure(0);
- continue;
- }
- /*
- * There is a race in here. Is okay, though, since
- * all it does is delay things by 30 seconds.
- */
- (void) pause();
- }
-}
-
-
-/*
- * bong - service and reschedule an alarm() interrupt
- */
-static RETSIGTYPE
-bong(sig)
-int sig;
-{
- if (config_timer > 0)
- config_timer--;
- if (resolve_timer > 0)
- resolve_timer--;
- alarm(ALARM_TIME);
-}
-
-
-/*
- * checkparent - see if our parent process is still running
- */
-static void
-checkparent()
-{
- /*
- * If our parent (the server) has died we will have been
- * inherited by init. If so, exit.
- */
- if (getppid() == 1) {
- syslog(LOG_INFO, "parent died before we finished, exiting");
- exit(0);
- }
-}
-
-
-/*
- * removeentry - we are done with an entry, remove it from the list
- */
-static void
-removeentry(entry)
- struct conf_entry *entry;
-{
- register struct conf_entry *ce;
-
- ce = confentries;
- if (ce == entry) {
- confentries = ce->ce_next;
- return;
- }
-
- while (ce != NULL) {
- if (ce->ce_next == entry) {
- ce->ce_next = entry->ce_next;
- return;
- }
- ce = ce->ce_next;
- }
-}
-
-
-/*
- * addentry - add an entry to the configuration list
- */
-static void
-addentry(name, mode, version, minpoll, maxpoll, flags, ttl, keyid)
- char *name;
- int mode;
- int version;
- int minpoll;
- int maxpoll;
- int flags;
- int ttl;
- U_LONG keyid;
-{
- register char *cp;
- register struct conf_entry *ce;
- int len;
-
- len = strlen(name) + 1;
- cp = emalloc((unsigned)len);
- memmove(cp, name, len);
-
- ce = (struct conf_entry *)emalloc(sizeof(struct conf_entry));
- ce->ce_name = cp;
- ce->ce_peeraddr = 0;
- ce->ce_hmode = (u_char)mode;
- ce->ce_version = (u_char)version;
- ce->ce_minpoll = (u_char)minpoll;
- ce->ce_maxpoll = (u_char)maxpoll;
- ce->ce_flags = (u_char)flags;
- ce->ce_ttl = (u_char)ttl;
- ce->ce_keyid = htonl(keyid);
- ce->ce_next = NULL;
-
- if (confentries == NULL) {
- confentries = ce;
- } else {
- register struct conf_entry *cep;
-
- for (cep = confentries; cep->ce_next != NULL;
- cep = cep->ce_next)
- /* nothing */;
- cep->ce_next = ce;
- }
-}
-
-
-/*
- * findhostaddr - resolve a host name into an address
- *
- * The routine sticks the address into the entry's ce_peeraddr if it
- * gets one. It returns 1 for "success" and 0 for an uncorrectable
- * failure. Note that "success" includes try again errors. You can
- * tell that you got a try again since ce_peeraddr will still be zero.
- */
-static int
-findhostaddr(entry)
- struct conf_entry *entry;
-{
- struct hostent *hp;
-
- checkparent(); /* make sure our guy is still running */
-
- hp = gethostbyname(entry->ce_name);
-
- if (hp == NULL) {
-#ifndef NODNS
- /*
- * If the resolver is in use, see if the failure is
- * temporary. If so, return success.
- */
- extern int h_errno;
-
- if (h_errno == TRY_AGAIN)
- return 1;
-#endif
- return (0);
- }
-
- /*
- * Use the first address. We don't have any way to
- * tell preferences and older gethostbyname() implementations
- * only return one.
- */
- memmove((char *)&(entry->ce_peeraddr),
- hp->h_addr,
- sizeof(struct in_addr));
- return (1);
-}
-
-
-/*
- * openntp - open a socket to the ntp server
- */
-static void
-openntp()
-{
- struct sockaddr_in saddr;
-
- if (sockfd >= 0)
- return;
-
- sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- if (sockfd == -1) {
- syslog(LOG_ERR, "socket() failed: %m");
- exit(1);
- }
-
- memset((char *)&saddr, 0, sizeof(saddr));
- saddr.sin_family = AF_INET;
- saddr.sin_port = htons(NTP_PORT); /* trash */
- saddr.sin_addr.s_addr = htonl(LOCALHOST); /* garbage */
-
-
- /*
- * Make the socket non-blocking. We'll wait with select()
- */
-#if defined(O_NONBLOCK)
- if (fcntl(sockfd, F_SETFL, O_NONBLOCK) == -1) {
- syslog(LOG_ERR, "fcntl(O_NONBLOCK) failed: %m");
- exit(1);
- }
-#else
-#if defined(FNDELAY)
- if (fcntl(sockfd, F_SETFL, FNDELAY) == -1) {
- syslog(LOG_ERR, "fcntl(FNDELAY) failed: %m");
- exit(1);
- }
-#else
-NEED NON BLOCKING IO
-#endif
-#endif
-
- if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
- syslog(LOG_ERR, "connect() failed: %m");
- exit(1);
- }
-}
-
-
-/*
- * request - send a configuration request to the server, wait for a response
- */
-static int
-request(conf)
- struct conf_peer *conf;
-{
- fd_set fdset;
- struct timeval tvout;
- struct req_pkt reqpkt;
- l_fp ts;
- int n;
-
- checkparent(); /* make sure our guy is still running */
-
- if (sockfd < 0)
- openntp();
-
- /*
- * Try to clear out any previously received traffic so it
- * doesn't fool us. Note the socket is nonblocking.
- */
- while (read(sockfd, (char *)&reqpkt, REQ_LEN_MAC) > 0)
- /* nothing */;
-
- /*
- * Make up a request packet with the configuration info
- */
- memset((char *)&reqpkt, 0, sizeof(reqpkt));
-
- reqpkt.rm_vn_mode = RM_VN_MODE(0, 0);
- reqpkt.auth_seq = AUTH_SEQ(1, 0); /* authenticated, no seq */
- reqpkt.implementation = IMPL_XNTPD; /* local implementation */
- reqpkt.request = REQ_CONFIG; /* configure a new peer */
- reqpkt.err_nitems = ERR_NITEMS(0, 1); /* one item */
- reqpkt.mbz_itemsize = MBZ_ITEMSIZE(sizeof(struct conf_peer));
- memmove(reqpkt.data, (char *)conf, sizeof(struct conf_peer));
- reqpkt.keyid = htonl(req_keyid);
-
- auth1crypt(req_keyid, (U_LONG *)&reqpkt, REQ_LEN_NOMAC);
- gettstamp(&ts);
- M_ADDUF(ts.l_ui, ts.l_uf, SKEWTIME);
- HTONL_FP(&ts, &reqpkt.tstamp);
- n = auth2crypt(req_keyid, (U_LONG *)&reqpkt, REQ_LEN_NOMAC);
-
- /*
- * Done. Send it.
- */
- n = write(sockfd, (char *)&reqpkt, REQ_LEN_NOMAC + n);
- if (n < 0) {
- syslog(LOG_ERR, "send to NTP server failed: %m");
- return 0; /* maybe should exit */
- }
-
- /*
- * Wait for a response. A weakness of the mode 7 protocol used
- * is that there is no way to associate a response with a
- * particular request, i.e. the response to this configuration
- * request is indistinguishable from that to any other. I should
- * fix this some day. In any event, the time out is fairly
- * pessimistic to make sure that if an answer is coming back
- * at all, we get it.
- */
- for (;;) {
- FD_ZERO(&fdset);
- FD_SET(sockfd, &fdset);
- tvout.tv_sec = TIMEOUT_SEC;
- tvout.tv_usec = TIMEOUT_USEC;
-
- n = select(sockfd + 1, &fdset, (fd_set *)0,
- (fd_set *)0, &tvout);
-
- if (n <= 0) {
- if (n < 0)
- syslog(LOG_ERR, "select() fails: %m");
- return 0;
- }
-
- n = read(sockfd, (char *)&reqpkt, REQ_LEN_MAC);
- if (n <= 0) {
- if (n < 0) {
- syslog(LOG_ERR, "read() fails: %m");
- return 0;
- }
- continue;
- }
-
- /*
- * Got one. Check through to make sure it is what
- * we expect.
- */
- if (n < RESP_HEADER_SIZE) {
- syslog(LOG_ERR, "received runt response (%d octets)",
- n);
- continue;
- }
-
- if (!ISRESPONSE(reqpkt.rm_vn_mode)) {
-#ifdef DEBUG
- if (debug > 1)
- printf("received non-response packet\n");
-#endif
- continue;
- }
-
- if (ISMORE(reqpkt.rm_vn_mode)) {
-#ifdef DEBUG
- if (debug > 1)
- printf("received fragmented packet\n");
-#endif
- continue;
- }
-
- if (INFO_VERSION(reqpkt.rm_vn_mode) != NTP_VERSION
- || INFO_MODE(reqpkt.rm_vn_mode) != MODE_PRIVATE) {
-#ifdef DEBUG
- if (debug > 1)
- printf("version (%d) or mode (%d) incorrect\n",
- INFO_VERSION(reqpkt.rm_vn_mode),
- INFO_MODE(reqpkt.rm_vn_mode));
-#endif
- continue;
- }
-
- if (INFO_SEQ(reqpkt.auth_seq) != 0) {
-#ifdef DEBUG
- if (debug > 1)
- printf("nonzero sequence number (%d)\n",
- INFO_SEQ(reqpkt.auth_seq));
-#endif
- continue;
- }
-
- if (reqpkt.implementation != IMPL_XNTPD ||
- reqpkt.request != REQ_CONFIG) {
-#ifdef DEBUG
- if (debug > 1)
- printf(
- "implementation (%d) or request (%d) incorrect\n",
- reqpkt.implementation, reqpkt.request);
-#endif
- continue;
- }
-
- if (INFO_NITEMS(reqpkt.err_nitems) != 0 ||
- INFO_MBZ(reqpkt.mbz_itemsize) != 0 ||
- INFO_ITEMSIZE(reqpkt.mbz_itemsize != 0)) {
-#ifdef DEBUG
- if (debug > 1)
- printf(
- "nitems (%d) mbz (%d) or itemsize (%d) nonzero\n",
- INFO_NITEMS(reqpkt.err_nitems),
- INFO_MBZ(reqpkt.mbz_itemsize),
- INFO_ITEMSIZE(reqpkt.mbz_itemsize));
-#endif
- continue;
- }
-
- n = INFO_ERR(reqpkt.err_nitems);
- switch (n) {
- case INFO_OKAY:
- /* success */
- return 1;
-
- case INFO_ERR_IMPL:
- syslog(LOG_ERR,
- "server reports implementation mismatch!!");
- return 0;
-
- case INFO_ERR_REQ:
- syslog(LOG_ERR,
- "server claims configuration request is unknown");
- return 0;
-
- case INFO_ERR_FMT:
- syslog(LOG_ERR,
- "server indicates a format error occured(!!)");
- return 0;
-
- case INFO_ERR_NODATA:
- syslog(LOG_ERR,
- "server indicates no data available (shouldn't happen)");
- return 0;
-
- case INFO_ERR_AUTH:
- syslog(LOG_ERR,
- "server returns a permission denied error");
- return 0;
-
- default:
- syslog(LOG_ERR,
- "server returns unknown error code %d", n);
- return 0;
- }
- }
-}
-
-
-/*
- * nexttoken - return the next token from a line
- */
-static char *
-nexttoken(lptr)
- char **lptr;
-{
- register char *cp;
- register char *tstart;
-
- cp = *lptr;
-
- /*
- * Skip leading white space
- */
- while (*cp == ' ' || *cp == '\t')
- cp++;
-
- /*
- * If this is the end of the line, return nothing.
- */
- if (*cp == '\n' || *cp == '\0') {
- *lptr = cp;
- return NULL;
- }
-
- /*
- * Must be the start of a token. Record the pointer and look
- * for the end.
- */
- tstart = cp++;
- while (*cp != ' ' && *cp != '\t' && *cp != '\n' && *cp != '\0')
- cp++;
-
- /*
- * Terminate the token with a \0. If this isn't the end of the
- * line, space to the next character.
- */
- if (*cp == '\n' || *cp == '\0')
- *cp = '\0';
- else
- *cp++ = '\0';
-
- *lptr = cp;
- return tstart;
-}
-
-
-/*
- * readconf - read the configuration information out of the file we
- * were passed. Note that since the file is supposed to be
- * machine generated, we bail out at the first sign of trouble.
- */
-static void
-readconf(fp, name)
- FILE *fp;
- char *name;
-{
- register int i;
- char *token[NUMTOK];
- U_LONG intval[NUMTOK];
- int flags;
- char buf[MAXLINESIZE];
- char *bp;
-
- while (fgets(buf, MAXLINESIZE, fp) != NULL) {
-
- bp = buf;
- for (i = 0; i < NUMTOK; i++) {
- if ((token[i] = nexttoken(&bp)) == NULL) {
- syslog(LOG_ERR,
- "tokenizing error in file `%s', quitting",
- name);
- exit(1);
- }
- }
-
- for (i = 1; i < NUMTOK; i++) {
- if (!atouint(token[i], &intval[i])) {
- syslog(LOG_ERR,
- "format error for integer token `%s', file `%s', quitting",
- token[i], name);
- exit(1);
- }
- }
-
- if (intval[TOK_HMODE] != MODE_ACTIVE &&
- intval[TOK_HMODE] != MODE_CLIENT &&
- intval[TOK_HMODE] != MODE_BROADCAST) {
- syslog(LOG_ERR, "invalid mode (%d) in file %s",
- intval[TOK_HMODE], name);
- exit(1);
- }
-
- if (intval[TOK_VERSION] > NTP_VERSION ||
- intval[TOK_VERSION] < NTP_OLDVERSION) {
- syslog(LOG_ERR, "invalid version (%d) in file %s",
- intval[TOK_VERSION], name);
- exit(1);
- }
-
- if (intval[TOK_MINPOLL] < NTP_MINPOLL ||
- intval[TOK_MINPOLL] > NTP_MAXPOLL) {
- syslog(LOG_ERR, "invalid MINPOLL value (%d) in file %s",
- intval[TOK_MINPOLL], name);
- exit(1);
- }
-
- if (intval[TOK_MAXPOLL] < NTP_MINPOLL ||
- intval[TOK_MAXPOLL] > NTP_MAXPOLL) {
- syslog(LOG_ERR, "invalid MAXPOLL value (%d) in file %s",
- intval[TOK_MAXPOLL], name);
- exit(1);
- }
-
- if ((intval[TOK_FLAGS] & ~(FLAG_AUTHENABLE|FLAG_PREFER))
- != 0) {
- syslog(LOG_ERR, "invalid flags (%d) in file %s",
- intval[TOK_FLAGS], name);
- exit(1);
- }
-
- flags = 0;
- if (intval[TOK_FLAGS] & FLAG_AUTHENABLE)
- flags |= CONF_FLAG_AUTHENABLE;
- if (intval[TOK_FLAGS] & FLAG_PREFER)
- flags |= CONF_FLAG_PREFER;
-
- /*
- * This is as good as we can check it. Add it in.
- */
- addentry(token[TOK_HOSTNAME], (int)intval[TOK_HMODE],
- (int)intval[TOK_VERSION], (int)intval[TOK_MINPOLL],
- (int)intval[TOK_MAXPOLL], flags, (int)intval[TOK_TTL],
- intval[TOK_KEYID]);
- }
-}
-
-
-/*
- * doconfigure - attempt to resolve names and configure the server
- */
-static void
-doconfigure(dores)
- int dores;
-{
- register struct conf_entry *ce;
- register struct conf_entry *ceremove;
-
- ce = confentries;
- while (ce != NULL) {
- if (dores && ce->ce_peeraddr == 0) {
- if (!findhostaddr(ce)) {
- syslog(LOG_ERR,
- "couldn't resolve `%s', giving up on it",
- ce->ce_name);
- ceremove = ce;
- ce = ceremove->ce_next;
- removeentry(ceremove);
- continue;
- }
- }
-
- if (ce->ce_peeraddr != 0) {
- if (request(&ce->ce_config)) {
- ceremove = ce;
- ce = ceremove->ce_next;
- removeentry(ceremove);
- continue;
- }
- }
- ce = ce->ce_next;
- }
-}
OpenPOWER on IntegriCloud