home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xntp3.zip / xntpd / refclock_local < prev    next >
Text File  |  1992-01-04  |  7KB  |  294 lines

  1. /*
  2.  * refclock_local - local pseudo-clock driver
  3.  */
  4. #include <stdio.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <sys/time.h>
  9.  
  10. #include "ntp_syslog.h"
  11. #include "ntp_fp.h"
  12. #include "ntp.h"
  13. #include "ntp_refclock.h"
  14.  
  15. #if defined(REFCLOCK) && defined(LOCAL_CLOCK)
  16. /*
  17.  * This is a hack to allow a machine to use its own system clock as
  18.  * a "reference clock", i.e. to free run against its own clock at
  19.  * a non-infinity stratum.  This is certainly useful if you want to
  20.  * use NTP in an isolated environment with no radio clock (not that
  21.  * this is a good idea) to synchronize the machines together.  Pick
  22.  * a machine that you figure has a good clock and configure it with
  23.  * a local reference clock running at stratum 0 (i.e. 127.127.1.0).
  24.  * Then point all the other machines at the one you're using as the
  25.  * reference.
  26.  *
  27.  * The other thing this is good for is if you want to use a particular
  28.  * server's clock as the last resort, when all radio time has gone
  29.  * away.  This is especially good if that server has an ovenized
  30.  * oscillator or something which will keep the time stable for extended
  31.  * periods, since then all the other machines can benefit from this.
  32.  * For this you would configure a local clock at a higher stratum (say
  33.  * 3 or 4) to prevent the server's stratum from falling below here.
  34.  */
  35.  
  36. /*
  37.  * Definitions
  38.  */
  39. #define    NUMUNITS    16    /* 127.127.1.[0-15] */
  40.  
  41. /*
  42.  * Some constant values we stick in the peer structure
  43.  */
  44. #define    LCLDISPERSION    (FP_SECOND*1)    /* 1 second dispersion */
  45. #define    LCLROOTDISPERSION (FP_SECOND*5)    /* 5 second root dispersion */
  46. #define    LCLPRECISION    (-5)        /* what the heck */
  47. #define    LCLREFID    "LCL\0"
  48. #define    LCLREFOFFSET    20        /* reftime is 20s behind */
  49. #define    LCLHSREFID    0x7f7f0101    /* 127.127.1.1 refid for hi stratum */
  50.  
  51. /*
  52.  * Description of clock
  53.  */
  54. #define    LCLDESCRIPTION    "Free running against local system clock"
  55.  
  56. /*
  57.  * Local clock unit control structure.
  58.  */
  59. struct lclunit {
  60.     struct peer *peer;        /* associated peer structure */
  61.     u_char status;            /* clock status */
  62.     u_char lastevent;        /* last clock event */
  63.     u_char unit;            /* unit number */
  64.     u_char unused;
  65.     u_long lastupdate;        /* last time data received */
  66.     u_long polls;            /* number of polls */
  67.     u_long timestarted;        /* time we started this */
  68. };
  69.  
  70.  
  71. /*
  72.  * Data space for the unit structures.  Note that we allocate these on
  73.  * the fly, but never give them back.
  74.  */
  75. static struct lclunit *lclunits[NUMUNITS];
  76. static u_char unitinuse[NUMUNITS];
  77.  
  78. /*
  79.  * Imported from the timer module
  80.  */
  81. extern u_long current_time;
  82.  
  83.  
  84. /*
  85.  * local_init - initialize internal local clock driver data
  86.  */
  87. void
  88. local_init()
  89. {
  90.     /*
  91.      * Just zero the data arrays
  92.      */
  93.     bzero((char *)lclunits, sizeof lclunits);
  94.     bzero((char *)unitinuse, sizeof unitinuse);
  95. }
  96.  
  97.  
  98. /*
  99.  * local_start - start up a local reference clock
  100.  */
  101. int
  102. local_start(unit, peer)
  103.     u_int unit;
  104.     struct peer *peer;
  105. {
  106.     register int i;
  107.     register struct lclunit *lcl;
  108.     extern char *emalloc();
  109.  
  110.     if (unit >= NUMUNITS) {
  111.         syslog(LOG_ERR, "local clock: unit number %d invalid (max 15)",
  112.             unit);
  113.         return 0;
  114.     }
  115.     if (unitinuse[unit]) {
  116.         syslog(LOG_ERR, "local clock: unit number %d in use", unit);
  117.         return 0;
  118.     }
  119.  
  120.     /*
  121.      * Looks like this might succeed.  Find memory for the structure.
  122.      * Look to see if there are any unused ones, if not we malloc()
  123.      * one.
  124.      */
  125.     if (lclunits[unit] != 0) {
  126.         lcl = lclunits[unit];    /* The one we want is okay */
  127.     } else {
  128.         for (i = 0; i < NUMUNITS; i++) {
  129.             if (!unitinuse[i] && lclunits[i] != 0)
  130.                 break;
  131.         }
  132.         if (i < NUMUNITS) {
  133.             /*
  134.              * Reclaim this one
  135.              */
  136.             lcl = lclunits[i];
  137.             lclunits[i] = 0;
  138.         } else {
  139.             lcl = (struct lclunit *)emalloc(sizeof(struct lclunit));
  140.         }
  141.     }
  142.     bzero((char *)lcl, sizeof(struct lclunit));
  143.     lclunits[unit] = lcl;
  144.  
  145.     /*
  146.      * Set up the structure
  147.      */
  148.     lcl->peer = peer;
  149.     lcl->unit = (u_char)unit;
  150.     lcl->timestarted = lcl->lastupdate = current_time;
  151.  
  152.     /*
  153.      * That was easy.  Diddle the peer variables and return success.
  154.      */
  155.     peer->precision = LCLPRECISION;
  156.     peer->rootdelay = 0;
  157.     peer->rootdispersion = LCLROOTDISPERSION;
  158.     peer->stratum = (u_char)unit;
  159.     if (unit <= 1)
  160.         bcopy(LCLREFID, (char *)&peer->refid, 4);
  161.     else
  162.         peer->refid = htonl(LCLHSREFID);
  163.     unitinuse[unit] = 1;
  164.     return 1;
  165. }
  166.  
  167.  
  168. /*
  169.  * local_shutdown - shut down a local clock
  170.  */
  171. void
  172. local_shutdown(unit)
  173.     int unit;
  174. {
  175.     if (unit >= NUMUNITS) {
  176.         syslog(LOG_ERR,
  177.         "local clock: INTERNAL ERROR, unit number %d invalid (max 15)",
  178.             unit);
  179.         return;
  180.     }
  181.     if (!unitinuse[unit]) {
  182.         syslog(LOG_ERR,
  183.         "local clock: INTERNAL ERROR, unit number %d not in use", unit);
  184.         return;
  185.     }
  186.  
  187.     unitinuse[unit] = 0;
  188. }
  189.  
  190.  
  191. /*
  192.  * local_poll - called by the transmit procedure
  193.  */
  194. void
  195. local_poll(unit, peer)
  196.     int unit;
  197.     struct peer *peer;
  198. {
  199.     l_fp off;
  200.     l_fp ts;
  201.     extern void get_systime();
  202.  
  203.     if (unit >= NUMUNITS) {
  204.         syslog(LOG_ERR, "local clock poll: INTERNAL: unit %d invalid",
  205.             unit);
  206.         return;
  207.     }
  208.     if (!unitinuse[unit]) {
  209.         syslog(LOG_ERR, "local clock poll: INTERNAL: unit %d unused",
  210.             unit);
  211.         return;
  212.     }
  213.     if (peer != lclunits[unit]->peer) {
  214.         syslog(LOG_ERR,
  215.             "local clock poll: INTERNAL: peer incorrect for unit %d",
  216.             unit);
  217.         return;
  218.     }
  219.  
  220.     /*
  221.      * Update clock stat counters
  222.      */
  223.     lclunits[unit]->polls++;
  224.     lclunits[unit]->lastupdate = current_time;
  225.  
  226.     /*
  227.      * This is pretty easy.  Give the reference clock support
  228.      * a zero offset and our fixed dispersion.  Use peer->xmt for
  229.      * our receive time.  Use peer->xmt - 20 seconds for our
  230.      * reference time.
  231.      */
  232.     off.l_ui = off.l_uf = 0;
  233.     ts = peer->xmt;
  234.     ts.l_ui -= LCLREFOFFSET;
  235.     refclock_receive(peer, &off, 0, LCLDISPERSION,
  236.         &ts, &peer->xmt, 0);
  237. }
  238.  
  239.  
  240.  
  241. /*
  242.  * local_control - set fudge factors, return statistics
  243.  */
  244. void
  245. local_control(unit, in, out)
  246.     u_int unit;
  247.     struct refclockstat *in;
  248.     struct refclockstat *out;
  249. {
  250.     extern s_fp drift_comp;
  251.  
  252.     if (unit >= NUMUNITS) {
  253.         syslog(LOG_ERR, "local clock: unit %d invalid (max %d)",
  254.             unit, NUMUNITS-1);
  255.         return;
  256.     }
  257.  
  258.     /*
  259.      * We only use the time1 fudge factor.  The drift compensation
  260.      * register is set to this if it is included in the incoming
  261.      * stuff and is shown in the outgoing stuff.
  262.      */
  263.     if (in != 0) {
  264.         if (in->haveflags & CLK_HAVETIME1)
  265.             drift_comp = LFPTOFP(&in->fudgetime1);
  266.     }
  267.     if (out != 0) {
  268.         out->type = REFCLK_LOCALCLOCK;
  269.         out->flags = 0;
  270.         out->haveflags = CLK_HAVETIME1;
  271.         out->clockdesc = LCLDESCRIPTION;
  272.         FPTOLFP(drift_comp, &out->fudgetime1);
  273.         out->fudgetime2.l_ui = out->fudgetime2.l_uf = 0;
  274.         out->fudgeval1 = out->fudgeval2 = 0;
  275.         out->lencode = 0;
  276.         out->lastcode = "";
  277.         out->badformat = 0;
  278.         out->baddata = 0;
  279.         out->noresponse = 0;
  280.         if (unitinuse[unit]) {
  281.             out->polls = lclunits[unit]->polls;
  282.             out->timereset =
  283.                 current_time - lclunits[unit]->timestarted;
  284.             out->lastevent = lclunits[unit]->lastevent;
  285.             out->currentstatus = lclunits[unit]->status;
  286.         } else {
  287.             out->polls = 0;
  288.             out->timereset = 0;
  289.             out->currentstatus = out->lastevent = CEVNT_NOMINAL;
  290.         }
  291.     }
  292. }
  293. #endif
  294.