]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 1503] Auto-enabling of monitor for "restrict ... limited" wrong.
authorDave Hart <hart@ntp.org>
Wed, 14 Apr 2010 04:44:52 +0000 (04:44 +0000)
committerDave Hart <hart@ntp.org>
Wed, 14 Apr 2010 04:44:52 +0000 (04:44 +0000)
[Bug 1504] ntpdate tickles ntpd "discard minimum 1" rate limit if
  "restrict ... limited" is used.

bk: 4bc54844aYpe8cMZ5Rry78f-Ct9KNw

13 files changed:
ChangeLog
include/ntp.h
include/ntp_lists.h
include/ntp_net.h
include/ntpd.h
ntpd/ntp_io.c
ntpd/ntp_monitor.c
ntpd/ntp_request.c
ntpd/ntp_restrict.c
ntpdate/ntpdate.c
ntpdate/ntpdate.h
ntpdc/ntpdc_ops.c
sntp/networking.c

index 7bcf74ffb486187cedba1b024ded68900fe643e9..47e7db3f88e3c3fee0d417c31f0515c1d8c67290 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,10 @@
 ---
+
+* [Bug 1503] Auto-enabling of monitor for "restrict ... limited" wrong.
+* [Bug 1504] ntpdate tickles ntpd "discard minimum 1" rate limit if
+  "restrict ... limited" is used.
+
+---
 (4.2.6p1) 2010/04/09 Released by Harlan Stenn <stenn@ntp.org>
 (4.2.6p1-RC6) 2010/03/31 Released by Harlan Stenn <stenn@ntp.org>
 
index b60523af1c8a46f46ddf35ed9df70e64a6d77b27..11285f47bd6686189e015f7dd3663f88f2cd6cf6 100644 (file)
@@ -4,6 +4,7 @@
 #ifndef NTP_H
 #define NTP_H
 
+#include <stddef.h>
 #include <math.h>
 
 #include <ntp_fp.h>
@@ -772,23 +773,31 @@ struct mon_data {
 /*
  * Structure used for restrictlist entries
  */
-struct restrictlist {
-       struct restrictlist *next;      /* link to next entry */
-       u_int32 addr;                   /* Ipv4 host address (host byte order) */
-       u_int32 mask;                   /* Ipv4 mask for address (host byte order) */
-       u_long count;                   /* number of packets matched */
-       u_short flags;                  /* accesslist flags */
-       u_short mflags;                 /* match flags */
-};
-
-struct restrictlist6 {
-       struct restrictlist6 *next;     /* link to next entry */
-       struct in6_addr addr6;          /* Ipv6 host address */
-       struct in6_addr mask6;          /* Ipv6 mask address */
-       u_long count;                   /* number of packets matched */
-       u_short flags;                  /* accesslist flags */
-       u_short mflags;                 /* match flags */
+typedef struct res_addr4_tag {
+       u_int32         addr;           /* IPv4 addr (host order) */
+       u_int32         mask;           /* IPv4 mask (host order) */
+} res_addr4;
+
+typedef struct res_addr6_tag {
+       struct in6_addr addr;           /* IPv6 addr (net order) */
+       struct in6_addr mask;           /* IPv6 mask (net order) */
+} res_addr6;
+
+typedef struct restrict_u_tag  restrict_u;
+struct restrict_u_tag {
+       restrict_u *            link;   /* link to next entry */
+       u_int32                 count;  /* number of packets matched */
+       u_short                 flags;  /* accesslist flags */
+       u_short                 mflags; /* match flags */
+       union {                         /* variant starting here */
+               res_addr4 v4;
+               res_addr6 v6;
+       } u;
 };
+#define        V4_SIZEOF_RESTRICT_U    (offsetof(restrict_u, u)        \
+                                + sizeof(res_addr4))
+#define        V6_SIZEOF_RESTRICT_U    (offsetof(restrict_u, u)        \
+                                + sizeof(res_addr6))
 
 
 /*
index 2bac38a52cbab1df9e67b5c3f87d1dea80f33a04..ee3f9c29950b510221478273f07952b2fa2c556c 100644 (file)
@@ -1,5 +1,8 @@
 /*
- * ntp_lists.h - singly-linked lists common code
+ * ntp_lists.h - linked lists common code
+ *
+ * SLIST: singly-linked lists
+ * ==========================
  *
  * These macros implement a simple singly-linked list template.  Both
  * the listhead and per-entry next fields are declared as pointers to
  * LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype)
  *     add entry at tail
  *
+ * LINK_SORT_SLIST(listhead, pentry, beforecur, nextlink, entrytype)
+ *     add entry in sorted order.  beforecur is an expression comparing
+ *     pentry with the current list entry.  The current entry can be
+ *     referenced within beforecur as L_S_S_CUR(), which is short for
+ *     LINK_SORT_SLIST_CUR().  beforecur is nonzero if pentry sorts
+ *     before L_S_S_CUR().
+ *
  * UNLINK_HEAD_SLIST(punlinked, listhead, nextlink)
  *     unlink first entry and point punlinked to it, or set punlinked
  *     to NULL if the list is empty.
  *
  * UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink, entrytype)
  *     unlink entry where expression expr is nonzero.  expr can refer
- *     to the entry being tested using UNLINK_EXPR_SLIST_CURRENT().
- *     See the implementation of UNLINK_SLIST() below for an example.
+ *     to the entry being tested using UNLINK_EXPR_SLIST_CURRENT(),
+ *     alias U_E_S_CUR().  See the implementation of UNLINK_SLIST()
+ *     below for an example.
  *     punlinked is pointed to the removed entry or NULL if none
  *     satisfy expr.
+ *
+ * DLIST: doubly-linked lists
+ * ==========================
+ *
+ * Elements on DLISTs always have non-NULL forward and back links,
+ * because both link chains are circular.  The beginning/end is marked
+ * by the listhead, which is the same type as elements for simplicity.
+ * An empty list's listhead has both links set to its own address.
+ *
+ *
  */
 #ifndef NTP_LISTS_H
 #define NTP_LISTS_H
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
+#ifndef TRUE
+# define TRUE  1
+# define NTP_LISTS_UNDEF_TRUE
 #endif
 
-#include <isc/list.h>
-
-
 #define LINK_SLIST(listhead, pentry, nextlink)                 \
 do {                                                           \
        (pentry)->nextlink = (listhead);                        \
@@ -63,6 +82,30 @@ do {                                                         \
        *pptail = (pentry);                                     \
 } while (0)
 
+#define LINK_SORT_SLIST_CURRENT()      (*ppentry)
+#define        L_S_S_CUR()                     LINK_SORT_SLIST_CURRENT()
+
+#define LINK_SORT_SLIST(listhead, pentry, beforecur, nextlink, \
+                       entrytype)                              \
+do {                                                           \
+       entrytype **ppentry;                                    \
+                                                               \
+       ppentry = &(listhead);                                  \
+       while (*ppentry != NULL) {                              \
+               if (beforecur) {                                \
+                       (pentry)->nextlink = *ppentry;          \
+                       *ppentry = (pentry);                    \
+                       break;                                  \
+               }                                               \
+               ppentry = &((*ppentry)->nextlink);              \
+               if (NULL == *ppentry) {                         \
+                       (pentry)->nextlink = NULL;              \
+                       *ppentry = (pentry);                    \
+                       break;                                  \
+               }                                               \
+       }                                                       \
+} while (0)
+
 #define UNLINK_HEAD_SLIST(punlinked, listhead, nextlink)       \
 do {                                                           \
        (punlinked) = (listhead);                               \
@@ -72,6 +115,9 @@ do {                                                         \
        }                                                       \
 } while (0)
 
+#define UNLINK_EXPR_SLIST_CURRENT()    (*ppentry)
+#define        U_E_S_CUR()                     UNLINK_EXPR_SLIST_CURRENT()
+
 #define UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink, \
                          entrytype)                            \
 do {                                                           \
@@ -94,11 +140,118 @@ do {                                                              \
        } else                                                  \
                (punlinked) = NULL;                             \
 } while (0)
-#define UNLINK_EXPR_SLIST_CURRENT()    (*ppentry)
 
 #define UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink, \
                     entrytype)                                 \
        UNLINK_EXPR_SLIST(punlinked, listhead, (ptounlink) ==   \
-           UNLINK_EXPR_SLIST_CURRENT(), nextlink, entrytype)
+           U_E_S_CUR(), nextlink, entrytype)
+
+#define CHECK_SLIST(listhead, nextlink, entrytype)             \
+do {                                                           \
+       entrytype *pentry;                                      \
+                                                               \
+       for (pentry = (listhead);                               \
+            pentry != NULL;                                    \
+            pentry = pentry->nextlink){                        \
+               NTP_INSIST(pentry != pentry->nextlink);         \
+               NTP_INSIST((listhead) != pentry->nextlink);     \
+       }                                                       \
+} while (0)
+
+/*
+ * DLIST
+ */
+#define DECL_DLIST_LINK(entrytype, link)                       \
+struct {                                                       \
+       entrytype *     b;                                      \
+       entrytype *     f;                                      \
+} link
+
+#define INIT_DLIST(listhead, link)                             \
+do {                                                           \
+       (listhead).link.f = &(listhead);                        \
+       (listhead).link.b = &(listhead);                        \
+} while (0)
+
+#define HEAD_DLIST(listhead, link)                             \
+       (                                                       \
+               (&(listhead) != (listhead).link.f)              \
+                   ? (listhead).link.f                         \
+                   : NULL                                      \
+       )
+
+#define TAIL_DLIST(listhead, link)                             \
+       (                                                       \
+               (&(listhead) != (listhead).link.b)              \
+                   ? (listhead).link.b                         \
+                   : NULL                                      \
+       )
+
+#define NEXT_DLIST(listhead, entry, link)                      \
+       (                                                       \
+               (&(listhead) != (entry)->link.f)                \
+                   ? (entry)->link.f                           \
+                   : NULL                                      \
+       )
+
+#define PREV_DLIST(listhead, entry, link)                      \
+       (                                                       \
+               (&(listhead) != (entry)->link.b)                \
+                   ? (entry)->link.b                           \
+                   : NULL                                      \
+       )
+
+#define LINK_DLIST(listhead, pentry, link)                     \
+do {                                                           \
+       (pentry)->link.f = (listhead).link.f;                   \
+       (pentry)->link.b = &(listhead);                         \
+       (listhead).link.f->link.b = (pentry);                   \
+       (listhead).link.f = (pentry);                           \
+} while (0)
+
+#define LINK_TAIL_DLIST(listhead, pentry, link)                        \
+do {                                                           \
+       (pentry)->link.b = (listhead).link.b;                   \
+       (pentry)->link.f = &(listhead);                         \
+       (listhead).link.b->link.f = (pentry);                   \
+       (listhead).link.b = (pentry);                           \
+} while (0)
+
+#define UNLINK_DLIST(ptounlink, link)                          \
+do {                                                           \
+       (ptounlink)->link.b->link.f = (ptounlink)->link.f;      \
+       (ptounlink)->link.f->link.b = (ptounlink)->link.b;      \
+       (ptounlink)->link.b = NULL;                             \
+       (ptounlink)->link.f = NULL;                             \
+} while (0)
+
+#define ITER_DLIST_BEGIN(listhead, iter, link, entrytype)      \
+{                                                              \
+       entrytype *i_dl_nextiter;                               \
+                                                               \
+       for ((iter) = (listhead).link.f;                        \
+            (iter) != &(listhead)                              \
+            && ((i_dl_nextiter = (iter)->link.f), TRUE);       \
+            (iter) = i_dl_nextiter) {
+#define ITER_DLIST_END()                                       \
+       }                                                       \
+}
+
+#define REV_ITER_DLIST_BEGIN(listhead, iter, link, entrytype)  \
+{                                                              \
+       entrytype *i_dl_nextiter;                               \
+                                                               \
+       for ((iter) = (listhead).link.b;                        \
+            (iter) != &(listhead)                              \
+            && ((i_dl_nextiter = (iter)->link.b), TRUE);       \
+            (iter) = i_dl_nextiter) {
+#define REV_ITER_DLIST_END()                                   \
+       }                                                       \
+}
+
+
+#ifdef NTP_LISTS_UNDEF_TRUE
+# undef TRUE
+#endif
 
 #endif /* NTP_LISTS_H */
index 9cfebe1c745c35d29697f6833a33cebf58b1b282..da2a22ab5bc7dd3e1c9121b1cef1118c12973f56 100644 (file)
@@ -17,7 +17,6 @@
 
 typedef union {
        struct sockaddr         sa;
-       struct sockaddr_storage sas;
        struct sockaddr_in      sa4;
        struct sockaddr_in6     sa6;
 } sockaddr_u;
@@ -31,7 +30,7 @@ typedef union {
 #define PSOCK_ADDR4(psau)      (&SOCK_ADDR4(psau))
 #define PSOCK_ADDR6(psau)      (&SOCK_ADDR6(psau))
 
-#define AF(psau)               ((psau)->sas.ss_family)
+#define AF(psau)               ((psau)->sa.sa_family)
 
 #define IS_IPV4(psau)          (AF_INET == AF(psau))
 #define IS_IPV6(psau)          (AF_INET6 == AF(psau))
@@ -95,6 +94,11 @@ typedef union {
            ? IN_CLASSD(SRCADR(psau))                           \
            : IN6_IS_ADDR_MULTICAST(PSOCK_ADDR6(psau)))
 
+#define SIZEOF_INADDR(fam)                                     \
+       ((AF_INET == (fam))                                     \
+           ? sizeof(struct in_addr)                            \
+           : sizeof(struct in6_addr))
+
 #define SIZEOF_SOCKADDR(fam)                                   \
        ((AF_INET == (fam))                                     \
            ? sizeof(struct sockaddr_in)                        \
@@ -106,11 +110,11 @@ typedef union {
            : sizeof((psau)->sa6))
 
 #define ZERO_SOCK(psau)                                                \
-       memset(&(psau)->sas, 0, sizeof((psau)->sas))
+       memset((psau), 0, sizeof(*(psau)))
 
 /* blast a byte value across sockaddr_u v6 address */
 #define        MEMSET_ADDR6(psau, v)                                   \
-       memset((void *)(psau)->sa6.sin6_addr.s6_addr, (v),      \
+       memset((psau)->sa6.sin6_addr.s6_addr, (v),              \
                sizeof((psau)->sa6.sin6_addr.s6_addr))
 
 #define SET_ONESMASK(psau)                                     \
@@ -129,19 +133,30 @@ typedef union {
                SET_ONESMASK(psau);                             \
        } while (0)
 
-/* compare a in6_addr with socket address */
+/* 
+ * compare two in6_addr returning negative, 0, or positive.
+ * ADDR6_CMP is negative if *pin6A is lower than *pin6B, zero if they
+ * are equal, positive if *pin6A is higher than *pin6B.  IN6ADDR_ANY
+ * is the lowest address (128 zero bits).
+ */
+#define        ADDR6_CMP(pin6A, pin6B)                                 \
+       memcmp((pin6A)->s6_addr, (pin6B)->s6_addr,              \
+              sizeof(pin6A)->s6_addr)
+
+/* compare two in6_addr for equality only */
 #if !defined(SYS_WINNT) || !defined(in_addr6)
-#define S_ADDR6_EQ(psau, my_in6_addr)                          \
-       (!memcmp(&(psau)->sa6.sin6_addr,                        \
-                (my_in6_addr),                                 \
-                sizeof((psau)->sa6.sin6_addr)))
+#define ADDR6_EQ(pin6A, pin6B)                                 \
+       (!ADDR6_CMP(pin6A, pin6B))
 #else
-#define S_ADDR6_EQ(psau, my_in6_addr)                          \
-       IN6_ADDR_EQUAL(&(psau)->sa6.sin6_addr,                  \
-                      (my_in6_addr))
+#define ADDR6_EQ(pin6A, pin6B)                                 \
+       IN6_ADDR_EQUAL(pin6A, pin6B)
 #endif
 
-/* are two sockaddr_u's addresses equal? */
+/* compare a in6_addr with socket address */
+#define        S_ADDR6_EQ(psau, pin6)                                  \
+       ADDR6_EQ(&(psau)->sa6.sin6_addr, pin6)
+
+/* are two sockaddr_u's addresses equal? (port excluded) */
 #define SOCK_EQ(psau1, psau2)                                  \
        ((AF(psau1) != AF(psau2))                               \
             ? 0                                                \
@@ -150,6 +165,12 @@ typedef union {
                   : (S_ADDR6_EQ((psau1), PSOCK_ADDR6(psau2))   \
                      && SCOPE_EQ((psau1), (psau2))))
 
+/* are two sockaddr_u's addresses and ports equal? */
+#define ADDR_PORT_EQ(psau1, psau2)                             \
+       ((NSRCPORT(psau1) != NSRCPORT(psau2)                    \
+            ? 0                                                \
+            : SOCK_EQ((psau1), (psau2))))
+
 /* is sockaddr_u address unspecified? */
 #define SOCK_UNSPEC(psau)                                      \
        (IS_IPV4(psau)                                          \
index 14cf0add2c9ae433ab4ac3ebe969de610aff9679..afb7ef4fc440bb85973a8b5eb845bd59bcda008f 100644 (file)
@@ -213,8 +213,8 @@ extern      void    process_private (struct recvbuf *, int);
 
 /* ntp_restrict.c */
 extern void    init_restrict   (void);
-extern int     restrictions    (sockaddr_u *);
-extern void    hack_restrict   (int, sockaddr_u *, sockaddr_u *, int, int);
+extern u_short restrictions    (sockaddr_u *);
+extern void    hack_restrict   (int, sockaddr_u *, sockaddr_u *, u_short, u_short);
 
 /* ntp_timer.c */
 extern void    init_timer      (void);
@@ -455,8 +455,8 @@ extern int  fdpps;                  /* pps file descriptor */
 extern keyid_t info_auth_keyid;        /* keyid used to authenticate requests */
 
 /* ntp_restrict.c */
-extern struct restrictlist *restrictlist; /* the ipv4 restriction list */
-extern struct restrictlist6 *restrictlist6; /* the ipv6 restriction list */
+extern restrict_u *    restrictlist4;  /* IPv4 restriction list */
+extern restrict_u *    restrictlist6;  /* IPv6 restriction list */
 extern int     ntp_minpkt;
 extern int     ntp_minpoll;
 extern int     mon_age;                /* monitor preempt age */
index 3cd8ab0cb1b9012aa3a97bcf7cf818b431c6d64c..7eaa9c0b6a14e6402451ffcea102ac85378737e4 100644 (file)
@@ -595,11 +595,11 @@ static void
 sockaddr_dump(sockaddr_u *psau)
 {
        /* Limit the size of the sockaddr_storage hex dump */
-       const int maxsize = min(32, sizeof(psau->sas));
+       const int maxsize = min(32, sizeof(psau->sa6));
        u_char *        cp;
        int             i;
 
-       cp = (u_char *)&psau->sas;
+       cp = (u_char *)&psau->sa;
 
        for(i = 0; i < maxsize; i++)
        {
index 05dca322e1a85a36a3edb39aef601171f86cb0d8..200a9028dd9fedfbd8f616b9143a52a09c328744 100644 (file)
@@ -310,9 +310,9 @@ ntp_monitor(
                 * Preempt from the MRU list if old enough.
                 */
                md = mon_mru_list.mru_prev;
-               if (md->count == 1 || ntp_random() / (2. * FRAC) >
-                   (double)(current_time - md->lasttime) / mon_age)
-                       return (flags & ~RES_LIMITED);
+               if (ntp_random() / (2. * FRAC) > (double)(current_time
+                   - md->lasttime) / mon_age)
+                       return (flags & ~(RES_LIMITED | RES_KOD));
 
                md->mru_prev->mru_next = &mon_mru_list;
                mon_mru_list.mru_prev = md->mru_prev;
@@ -329,7 +329,7 @@ ntp_monitor(
         */
        md->lasttime = md->firsttime = current_time;
        md->count = 1;
-       md->flags = flags & ~RES_LIMITED;
+       md->flags = flags & ~(RES_LIMITED | RES_KOD);
        md->leak = 0;
        memset(&md->rmtadr, 0, sizeof(md->rmtadr));
        memcpy(&md->rmtadr, &addr, sizeof(addr));
index c863d2c5677ebed5f22fb08217b5e6ed91a36934..95cb1e5c2b69ca13e3906ece22ccaf4f5dec73a7 100644 (file)
@@ -848,7 +848,7 @@ peer_info (
                        NSRCADR(&addr) = ipl->addr;
                }
 #ifdef ISC_PLATFORM_HAVESALEN
-               addr.sas.ss_len = SOCKLEN(&addr);
+               addr.sa.sa_len = SOCKLEN(&addr);
 #endif
                ipl++;
                if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0)
@@ -981,7 +981,7 @@ peer_stats (
                        NSRCADR(&addr) = ipl->addr;
                }       
 #ifdef ISC_PLATFORM_HAVESALEN
-               addr.sas.ss_len = SOCKLEN(&addr);
+               addr.sa.sa_len = SOCKLEN(&addr);
 #endif
                DPRINTF(1, ("peer_stats: looking for %s, %d, %d\n",
                            stoa(&addr), ipl->port, NSRCPORT(&addr)));
@@ -1407,7 +1407,7 @@ do_conf(
                }
                NSRCPORT(&peeraddr) = htons(NTP_PORT);
 #ifdef ISC_PLATFORM_HAVESALEN
-               peeraddr.sas.ss_len = SOCKLEN(&peeraddr);
+               peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
 #endif
 
                /* XXX W2DO? minpoll/maxpoll arguments ??? */
@@ -1571,7 +1571,7 @@ do_unconf(
                }
                SET_PORT(&peeraddr, NTP_PORT);
 #ifdef ISC_PLATFORM_HAVESALEN
-               peeraddr.sas.ss_len = SOCKLEN(&peeraddr);
+               peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
 #endif
                found = 0;
                peer = NULL;
@@ -1616,7 +1616,7 @@ do_unconf(
                }
                SET_PORT(&peeraddr, NTP_PORT);
 #ifdef ISC_PLATFORM_HAVESALEN
-               peeraddr.sas.ss_len = SOCKLEN(&peeraddr);
+               peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
 #endif
                found = 0;
                peer = NULL;
@@ -1731,6 +1731,58 @@ setclr_flags(
                loop_config(LOOP_DRIFTCOMP, drift_comp);
 }
 
+/*
+ * list_restrict4 - recursive helper for list_restrict dumps IPv4
+ *                 restriction list in reverse order.
+ */
+static void
+list_restrict4(
+       restrict_u *            res,
+       struct info_restrict ** ppir
+       )
+{
+       struct info_restrict *  pir;
+
+       if (res->link != NULL)
+               list_restrict4(res->link, ppir);
+
+       pir = *ppir;
+       pir->addr = htonl(res->u.v4.addr);
+       if (client_v6_capable) 
+               pir->v6_flag = 0;
+       pir->mask = htonl(res->u.v4.mask);
+       pir->count = htonl(res->count);
+       pir->flags = htons(res->flags);
+       pir->mflags = htons(res->mflags);
+       *ppir = (struct info_restrict *)more_pkt();
+}
+
+
+/*
+ * list_restrict6 - recursive helper for list_restrict dumps IPv6
+ *                 restriction list in reverse order.
+ */
+static void
+list_restrict6(
+       restrict_u *            res,
+       struct info_restrict ** ppir
+       )
+{
+       struct info_restrict *  pir;
+
+       if (res->link != NULL)
+               list_restrict6(res->link, ppir);
+
+       pir = *ppir;
+       pir->addr6 = res->u.v6.addr; 
+       pir->mask6 = res->u.v6.mask;
+       pir->v6_flag = 1;
+       pir->count = htonl(res->count);
+       pir->flags = htons(res->flags);
+       pir->mflags = htons(res->mflags);
+       *ppir = (struct info_restrict *)more_pkt();
+}
+
 
 /*
  * list_restrict - return the restrict list
@@ -1742,43 +1794,26 @@ list_restrict(
        struct req_pkt *inpkt
        )
 {
-       register struct info_restrict *ir;
-       register struct restrictlist *rl;
-       register struct restrictlist6 *rl6;
+       struct info_restrict *ir;
 
-#ifdef DEBUG
-       if (debug > 2)
-           printf("wants restrict list summary\n");
-#endif
+       DPRINTF(3, ("wants restrict list summary\n"));
 
        ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt,
            v6sizeof(struct info_restrict));
        
-       for (rl = restrictlist; rl != 0 && ir != 0; rl = rl->next) {
-               ir->addr = htonl(rl->addr);
-               if (client_v6_capable) 
-                       ir->v6_flag = 0;
-               ir->mask = htonl(rl->mask);
-               ir->count = htonl((u_int32)rl->count);
-               ir->flags = htons(rl->flags);
-               ir->mflags = htons(rl->mflags);
-               ir = (struct info_restrict *)more_pkt();
-       }
+       /*
+        * The restriction lists are kept sorted in the reverse order
+        * than they were originally.  To preserve the output semantics,
+        * dump each list in reverse order.  A recursive helper function
+        * achieves that.
+        */
+       list_restrict4(restrictlist4, &ir);
        if (client_v6_capable)
-               for (rl6 = restrictlist6; rl6 != 0 && ir != 0; rl6 = rl6->next) {
-                       ir->addr6 = rl6->addr6;
-                       ir->mask6 = rl6->mask6;
-                       ir->v6_flag = 1;
-                       ir->count = htonl((u_int32)rl6->count);
-                       ir->flags = htons(rl6->flags);
-                       ir->mflags = htons(rl6->mflags);
-                       ir = (struct info_restrict *)more_pkt();
-               }
+               list_restrict6(restrictlist6, &ir);
        flush_pkt();
 }
 
 
-
 /*
  * do_resaddflags - add flags to a restrict entry (or create one)
  */
@@ -2100,7 +2135,7 @@ reset_peer(
                }
 
 #ifdef ISC_PLATFORM_HAVESALEN
-               peeraddr.sas.ss_len = SOCKLEN(&peeraddr);
+               peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
 #endif
                peer = findexistingpeer(&peeraddr, NULL, -1);
                if (NULL == peer)
@@ -2131,7 +2166,7 @@ reset_peer(
                }
                SET_PORT(&peeraddr, 123);
 #ifdef ISC_PLATFORM_HAVESALEN
-               peeraddr.sas.ss_len = SOCKLEN(&peeraddr);
+               peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
 #endif
                peer = findexistingpeer(&peeraddr, NULL, -1);
                while (peer != NULL) {
@@ -2637,7 +2672,7 @@ get_clock_info(
        ZERO_SOCK(&addr);
        AF(&addr) = AF_INET;
 #ifdef ISC_PLATFORM_HAVESALEN
-       addr.sas.ss_len = SOCKLEN(&addr);
+       addr.sa.sa_len = SOCKLEN(&addr);
 #endif
        SET_PORT(&addr, NTP_PORT);
        items = INFO_NITEMS(inpkt->err_nitems);
@@ -2709,7 +2744,7 @@ set_clock_fudge(
                AF(&addr) = AF_INET;
                NSRCADR(&addr) = cf->clockadr;
 #ifdef ISC_PLATFORM_HAVESALEN
-               addr.sas.ss_len = SOCKLEN(&addr);
+               addr.sa.sa_len = SOCKLEN(&addr);
 #endif
                SET_PORT(&addr, NTP_PORT);
                if (!ISREFCLOCKADR(&addr) ||
@@ -2776,7 +2811,7 @@ get_clkbug_info(
        ZERO_SOCK(&addr);
        AF(&addr) = AF_INET;
 #ifdef ISC_PLATFORM_HAVESALEN
-       addr.sas.ss_len = SOCKLEN(&addr);
+       addr.sa.sa_len = SOCKLEN(&addr);
 #endif
        SET_PORT(&addr, NTP_PORT);
        items = INFO_NITEMS(inpkt->err_nitems);
index 2ea4f35aae078db57de3fba1e6d44561a0a5c233..e087b6ce441a492f3caaa78c7adacc5398159288 100644 (file)
@@ -10,7 +10,9 @@
 
 #include "ntpd.h"
 #include "ntp_if.h"
+#include "ntp_lists.h"
 #include "ntp_stdlib.h"
+#include "ntp_assert.h"
 
 /*
  * This code keeps a simple address-and-mask list of hosts we want
  * addresses. This is not protocol-independant but for now I can't
  * find a way to respect this. We'll check this later... JFB 07/2001
  */
-#define SET_IPV6_ADDR_MASK(dst, src, msk) \
-       do { \
-               int idx; \
-               for (idx = 0; idx < 16; idx++) { \
-                       (dst)->s6_addr[idx] = \
-                           (u_char) ((src)->s6_addr[idx] & (msk)->s6_addr[idx]); \
-               } \
+#define MASK_IPV6_ADDR(dst, src, msk)                                  \
+       do {                                                            \
+               int idx;                                                \
+               for (idx = 0; idx < COUNTOF((dst)->s6_addr); idx++) {   \
+                       (dst)->s6_addr[idx] = (src)->s6_addr[idx]       \
+                                             & (msk)->s6_addr[idx];    \
+               }                                                       \
        } while (0)
 
 /*
- * Memory allocation parameters.  We allocate INITRESLIST entries
- * initially, and add INCRESLIST entries to the free list whenever
- * we run out.
+ * We allocate INC_RESLIST{4|6} entries to the free list whenever empty.
+ * Auto-tune these to be just less than 1KB (leaving at least 16 bytes
+ * for allocator overhead).
  */
-#define        INITRESLIST     10
-#define        INCRESLIST      5
+#define        INC_RESLIST4    ((1024 - 16) / V4_SIZEOF_RESTRICT_U)
+#define        INC_RESLIST6    ((1024 - 16) / V6_SIZEOF_RESTRICT_U)
 
 /*
  * The restriction list
  */
-struct restrictlist *restrictlist;
-struct restrictlist6 *restrictlist6;
-static int restrictcount;      /* count of entries in the res list */
-static int restrictcount6;     /* count of entries in the res list 2*/
+restrict_u *restrictlist4;
+restrict_u *restrictlist6;
+static int restrictcount;      /* count in the restrict lists */
 
 /*
  * The free list and associated counters.  Also some uninteresting
  * stat counters.
  */
-static struct restrictlist *resfree;
-static struct restrictlist6 *resfree6;
-static int numresfree;         /* number of struct on free list */
-static int numresfree6;        /* number of struct on free list 2 */
+static restrict_u *resfree4;   /* available entries (free list) */
+static restrict_u *resfree6;
 
 static u_long res_calls;
 static u_long res_found;
 static u_long res_not_found;
 
 /*
- * Count number of restriction entries referring to RES_LIMITED controls
- * activation/deactivation of monitoring (with respect to RES_LIMITED
- * control)
+ * Count number of restriction entries referring to RES_LIMITED, to
+ * control implicit activation/deactivation of the MRU monlist.
  */
 static u_long res_limited_refcnt;
-static u_long res_limited_refcnt6;
 
 /*
- * Our initial allocation of lists entries.
+ * Our default entries.
  */
-static struct restrictlist resinit[INITRESLIST];
-static struct restrictlist6 resinit6[INITRESLIST];
+static restrict_u      restrict_def4;
+static restrict_u      restrict_def6;
+
+/*
+ * "restrict source ..." enabled knob and restriction bits.
+ */
+static int             restrict_source_enabled;
+static u_short         restrict_source_flags;
+static u_short         restrict_source_mflags;
+
+/*
+ * private functions
+ */
+static restrict_u *    alloc_res4(void);
+static restrict_u *    alloc_res6(void);
+static void            free_res(restrict_u *, int);
+static void            inc_res_limited(void);
+static void            dec_res_limited(void);
+static restrict_u *    match_restrict4_addr(u_int32, u_short);
+static restrict_u *    match_restrict6_addr(const struct in6_addr *,
+                                            u_short);
+static restrict_u *    match_restrict_entry(const restrict_u *, int);
+static int             res_sorts_before4(restrict_u *, restrict_u *);
+static int             res_sorts_before6(restrict_u *, restrict_u *);
 
 
 /*
@@ -100,81 +119,306 @@ static   struct restrictlist6 resinit6[INITRESLIST];
 void
 init_restrict(void)
 {
-       register int i;
-
        /*
-        * Zero the list and put all but one on the free list
+        * The restriction lists begin with a default entry with address
+        * and mask 0, which will match any entry.  The lists are kept
+        * sorted by descending address followed by descending mask:
+        *
+        *   address      mask
+        * 192.168.0.0  255.255.255.0   kod limited noquery nopeer
+        * 192.168.0.0  255.255.0.0     kod limited
+        * 0.0.0.0      0.0.0.0         kod limited noquery
+        *
+        * The first entry which matches an address is used.  With the
+        * example restrictions above, 192.168.0.0/24 matches the first
+        * entry, the rest of 192.168.0.0/16 matches the second, and
+        * everything else matches the third (default).
+        *
+        * Note this achieves the same result a little more efficiently
+        * than the documented behavior, which is to keep the lists
+        * sorted by ascending address followed by ascending mask, with
+        * the _last_ matching entry used.
+        *
+        * An additional wrinkle is we may have multiple entries with
+        * the same address and mask but differing match flags (mflags).
+        * At present there is only one, RESM_NTPONLY.  Entries with
+        * RESM_NTPONLY are sorted earlier so they take precedence over
+        * any otherwise similar entry without.  Again, this is the same
+        * behavior as but reversed implementation compared to the docs.
+        * 
         */
-       resfree = 0;
-       memset((char *)resinit, 0, sizeof resinit);
-       resfree6 = 0;
-       memset((char *)resinit6, 0, sizeof resinit6);
-       for (i = 1; i < INITRESLIST; i++) {
-               resinit[i].next = resfree;
-               resinit6[i].next = resfree6;
-               resfree = &resinit[i];
-               resfree6 = &resinit6[i];
+       LINK_SLIST(restrictlist4, &restrict_def4, link);
+       LINK_SLIST(restrictlist6, &restrict_def6, link);
+       restrictcount = 2;
+}
+
+
+static restrict_u *
+alloc_res4(void)
+{
+       const size_t    cb = V4_SIZEOF_RESTRICT_U;
+       const size_t    count = INC_RESLIST4;
+       restrict_u *    rl;
+       restrict_u *    res;
+       int             i;
+
+       UNLINK_HEAD_SLIST(res, resfree4, link);
+       if (res != NULL)
+               return res;
+
+       rl = emalloc(count * cb);
+       memset(rl, 0, count * cb);
+       /* link all but the first onto free list */
+       res = (void *)((char *)rl + (count - 1) * cb);
+       for (i = count - 1; i > 0; i--) {
+               LINK_SLIST(resfree4, res, link);
+               res = (void *)((char *)res - cb);
        }
-       numresfree = INITRESLIST-1;
-       numresfree6 = INITRESLIST-1;
+       NTP_INSIST(rl == res);
+       /* allocate the first */
+       return res;
+}
 
-       /*
-        * Put the remaining item at the head of the list as our default
-        * entry. Everything in here should be zero for now.
-        */
-       resinit[0].addr = htonl(INADDR_ANY);
-       resinit[0].mask = 0;
-       memset(&resinit6[0].addr6, 0, sizeof(struct in6_addr)); 
-       memset(&resinit6[0].mask6, 0, sizeof(struct in6_addr)); 
-       restrictlist = &resinit[0];
-       restrictlist6 = &resinit6[0];
-       restrictcount = 1;
-       restrictcount = 2;
 
-       /*
-        * fix up stat counters
-        */
-       res_calls = 0;
-       res_found = 0;
-       res_not_found = 0;
+static restrict_u *
+alloc_res6(void)
+{
+       const size_t    cb = V6_SIZEOF_RESTRICT_U;
+       const size_t    count = INC_RESLIST6;
+       restrict_u *    rl;
+       restrict_u *    res;
+       int             i;
+
+       UNLINK_HEAD_SLIST(res, resfree6, link);
+       if (res != NULL)
+               return res;
+
+       rl = emalloc(count * cb);
+       memset(rl, 0, count * cb);
+       /* link all but the first onto free list */
+       res = (void *)((char *)rl + (count - 1) * cb);
+       for (i = count - 1; i > 0; i--) {
+               LINK_SLIST(resfree6, res, link);
+               res = (void *)((char *)res - cb);
+       }
+       NTP_INSIST(rl == res);
+       /* allocate the first */
+       return res;
+}
 
-       /*
-        * set default values for RES_LIMIT functionality
-        */
-       res_limited_refcnt = 0;
-       res_limited_refcnt6 = 0;
+
+static void
+free_res(
+       restrict_u *    res,
+       int             v6
+       )
+{
+       restrict_u **   plisthead;
+       restrict_u *    unlinked;
+
+       restrictcount--;
+       if (RES_LIMITED && res->flags)
+               dec_res_limited();
+
+       if (v6)
+               plisthead = &restrictlist6;
+       else
+               plisthead = &restrictlist4;
+       UNLINK_SLIST(unlinked, *plisthead, res, link, restrict_u);
+       NTP_INSIST(unlinked == res);
+
+       if (v6) {
+               memset(res, 0, V6_SIZEOF_RESTRICT_U);
+               plisthead = &resfree6;
+       } else {
+               memset(res, 0, V4_SIZEOF_RESTRICT_U);
+               plisthead = &resfree4;
+       }
+       LINK_SLIST(*plisthead, res, link);
+}
+
+
+static void
+inc_res_limited(void)
+{
+       if (!res_limited_refcnt)
+               mon_start(MON_RES);
+       res_limited_refcnt++;
+}
+
+
+static void
+dec_res_limited(void)
+{
+       res_limited_refcnt--;
+       if (!res_limited_refcnt)
+               mon_stop(MON_RES);
+}
+
+
+static restrict_u *
+match_restrict4_addr(
+       u_int32 addr,
+       u_short port
+       )
+{
+       restrict_u *    res;
+       restrict_u *    next;
+
+       for (res = restrictlist4; res != NULL; res = next) {
+               next = res->link;
+               if (res->u.v4.addr == (addr & res->u.v4.mask)
+                   && (!(RESM_NTPONLY & res->mflags)
+                       || NTP_PORT == port))
+                       break;
+       }
+       return res;
+}
+
+
+static restrict_u *
+match_restrict6_addr(
+       const struct in6_addr * addr,
+       u_short                 port
+       )
+{
+       restrict_u *    res;
+       restrict_u *    next;
+       struct in6_addr masked;
+
+       for (res = restrictlist6; res != NULL; res = next) {
+               next = res->link;
+               NTP_INSIST(next != res);
+               MASK_IPV6_ADDR(&masked, addr, &res->u.v6.mask);
+               if (ADDR6_EQ(&masked, &res->u.v6.addr)
+                   && (!(RESM_NTPONLY & res->mflags)
+                       || NTP_PORT == port))
+                       break;
+       }
+       return res;
+}
+
+
+/*
+ * match_restrict_entry - find an exact match on a restrict list.
+ *
+ * Exact match is addr, mask, and mflags all equal.
+ * In order to use more common code for IPv4 and IPv6, this routine
+ * requires the caller to populate a restrict_u with mflags and either
+ * the v4 or v6 address and mask as appropriate.  Other fields in the
+ * input restrict_u are ignored.
+ */
+static restrict_u *
+match_restrict_entry(
+       const restrict_u *      pmatch,
+       int                     v6
+       )
+{
+       restrict_u *res;
+       restrict_u *rlist;
+       size_t cb;
+
+       if (v6) {
+               rlist = restrictlist6;
+               cb = sizeof(pmatch->u.v6);
+       } else {
+               rlist = restrictlist4;
+               cb = sizeof(pmatch->u.v4);
+       }
+
+       for (res = rlist; res != NULL; res = res->link)
+               if (res->mflags == pmatch->mflags &&
+                   !memcmp(&res->u, &pmatch->u, cb))
+                       break;
+       return res;
+}
+
+
+/*
+ * res_sorts_before4 - compare two restrict4 entries
+ *
+ * Returns nonzero if r1 sorts before r2.  We sort by descending
+ * address, then descending mask, then descending mflags, so sorting
+ * before means having a higher value.
+ */
+static int
+res_sorts_before4(
+       restrict_u *r1,
+       restrict_u *r2
+       )
+{
+       int r1_before_r2;
+
+       if (r1->u.v4.addr > r2->u.v4.addr)
+               r1_before_r2 = 1;
+       else if (r1->u.v4.addr < r2->u.v4.addr)
+               r1_before_r2 = 0;
+       else if (r1->u.v4.mask > r2->u.v4.mask)
+               r1_before_r2 = 1;
+       else if (r1->u.v4.mask < r2->u.v4.mask)
+               r1_before_r2 = 0;
+       else if (r1->mflags > r2->mflags)
+               r1_before_r2 = 1;
+       else
+               r1_before_r2 = 0;
+
+       return r1_before_r2;
+}
+
+
+/*
+ * res_sorts_before6 - compare two restrict6 entries
+ *
+ * Returns nonzero if r1 sorts before r2.  We sort by descending
+ * address, then descending mask, then descending mflags, so sorting
+ * before means having a higher value.
+ */
+static int
+res_sorts_before6(
+       restrict_u *r1,
+       restrict_u *r2
+       )
+{
+       int r1_before_r2;
+       int cmp;
+
+       cmp = ADDR6_CMP(&r1->u.v6.addr, &r2->u.v6.addr);
+       if (cmp > 0)            /* r1->addr > r2->addr */
+               r1_before_r2 = 1;
+       else if (cmp < 0)       /* r2->addr > r1->addr */
+               r1_before_r2 = 0;
+       else {
+               cmp = ADDR6_CMP(&r1->u.v6.mask, &r2->u.v6.mask);
+               if (cmp > 0)            /* r1->mask > r2->mask*/
+                       r1_before_r2 = 1;
+               else if (cmp < 0)       /* r2->mask > r1->mask */
+                       r1_before_r2 = 0;
+               else if (r1->mflags > r2->mflags)
+                       r1_before_r2 = 1;
+               else
+                       r1_before_r2 = 0;
+       }
+
+       return r1_before_r2;
 }
 
 
 /*
  * restrictions - return restrictions for this host
  */
-int
+u_short
 restrictions(
        sockaddr_u *srcadr
        )
 {
-       struct restrictlist *rl;
-       struct restrictlist *match = NULL;
-       struct restrictlist6 *rl6;
-       struct restrictlist6 *match6 = NULL;
-       struct in6_addr hostaddr6;
-       struct in6_addr hostservaddr6;
-       u_int32 hostaddr;
-       int     flags = 0;
-       int     isntpport;
+       restrict_u *match;
+       struct in6_addr *pin6;
+       u_short flags;
 
        res_calls++;
+       flags = 0;
        /* IPv4 source address */
        if (IS_IPV4(srcadr)) {
-
-               /*
-                * We need the host address in host order. Also need to
-                * know whether this is from the ntp port or not.
-                */
-               hostaddr = SRCADR(srcadr);
-               isntpport = (NTP_PORT == SRCPORT(srcadr));
-
                /*
                 * Ignore any packets with a multicast source address
                 * (this should be done early in the receive process,
@@ -183,21 +427,15 @@ restrictions(
                if (IN_CLASSD(SRCADR(srcadr)))
                        return (int)RES_IGNORE;
 
+               match = match_restrict4_addr(SRCADR(srcadr),
+                                            SRCPORT(srcadr));
+               match->count++;
                /*
-                * Set match to first entry, which is default entry.
-                * Work our way down from there.
+                * res_not_found counts only use of the final default
+                * entry, not any "restrict default ntpport ...", which
+                * would be just before the final default.
                 */
-               match = restrictlist;
-               for (rl = match->next; rl != 0 && rl->addr <= hostaddr;
-                   rl = rl->next)
-                       if ((hostaddr & rl->mask) == rl->addr) {
-                               if ((rl->mflags & RESM_NTPONLY) &&
-                                   !isntpport)
-                                       continue;
-                               match = rl;
-                       }
-               match->count++;
-               if (match == restrictlist)
+               if (&restrict_def4 == match)
                        res_not_found++;
                else
                        res_found++;
@@ -206,46 +444,23 @@ restrictions(
 
        /* IPv6 source address */
        if (IS_IPV6(srcadr)) {
-
-               /*
-                * We need the host address in network order. Also need
-                * to know whether this is from the ntp port or not.
-                */
-               hostaddr6 = SOCK_ADDR6(srcadr);
-               isntpport = (NTP_PORT == SRCPORT(srcadr));
+               pin6 = PSOCK_ADDR6(srcadr);
 
                /*
                 * Ignore any packets with a multicast source address
                 * (this should be done early in the receive process,
                 * not later!)
                 */
-               if (IN6_IS_ADDR_MULTICAST(&hostaddr6))
+               if (IN6_IS_ADDR_MULTICAST(pin6))
                        return (int)RES_IGNORE;
 
-               /*
-                * Set match to first entry, which is default entry.
-                *  Work our way down from there.
-                */
-               match6 = restrictlist6;
-               for (rl6 = match6->next; rl6 != 0 &&
-                   (memcmp(&(rl6->addr6), &hostaddr6,
-                   sizeof(hostaddr6)) <= 0); rl6 = rl6->next) {
-                       SET_IPV6_ADDR_MASK(&hostservaddr6, &hostaddr6,
-                           &rl6->mask6);
-                       if (memcmp(&hostservaddr6, &(rl6->addr6),
-                           sizeof(hostservaddr6)) == 0) {
-                               if ((rl6->mflags & RESM_NTPONLY) &&
-                                   !isntpport)
-                                       continue;
-                               match6 = rl6;
-                       }
-               }
-               match6->count++;
-               if (match6 == restrictlist6)
+               match = match_restrict6_addr(pin6, SRCPORT(srcadr));
+               match->count++;
+               if (&restrict_def6 == match)
                        res_not_found++;
                else
                        res_found++;
-               flags = match6->flags;
+               flags = match->flags;
        }
        return (flags);
 }
@@ -256,326 +471,130 @@ restrictions(
  */
 void
 hack_restrict(
-       int op,
-       sockaddr_u *resaddr,
-       sockaddr_u *resmask,
-       int mflags,
-       int flags
+       int             op,
+       sockaddr_u *    resaddr,
+       sockaddr_u *    resmask,
+       u_short         mflags,
+       u_short         flags
        )
 {
-       register u_int32 addr = 0;
-       register u_int32 mask = 0;
-       struct in6_addr addr6;
-       struct in6_addr mask6;
-       register struct restrictlist *rl = NULL;
-       register struct restrictlist *rlprev = NULL;
-       register struct restrictlist6 *rl6 = NULL;
-       register struct restrictlist6 *rlprev6 = NULL;
-       int i, addr_cmp, mask_cmp;
-       memset(&addr6, 0, sizeof(struct in6_addr)); 
-       memset(&mask6, 0, sizeof(struct in6_addr)); 
-
-       if (IS_IPV4(resaddr)) {
+       int             v6;
+       restrict_u      match;
+       restrict_u *    res;
+       restrict_u **   plisthead;
+
+       DPRINTF(1, ("restrict: op %d addr %s mask %s mflags %08x flags %08x\n",
+                   op, stoa(resaddr), stoa(resmask), mflags, flags));
+
+       if (NULL == resaddr) {
+               NTP_REQUIRE(NULL == resmask);
+               NTP_REQUIRE(RESTRICT_FLAGS == op);
+               restrict_source_flags = flags;
+               restrict_source_mflags = mflags;
+               restrict_source_enabled = 1;
+               return;
+       }
 
-               DPRINTF(1, ("restrict: addr %08x mask %08x mflags %08x flags %08x\n",
-                           SRCADR(resaddr), SRCADR(resmask), mflags, flags));
+       memset(&match, 0, sizeof(match));
+       /* silence VC9 potentially uninit warnings */
+       res = NULL;
+       v6 = 0;
 
+       if (IS_IPV4(resaddr)) {
+               v6 = 0;
                /*
-                * Get address and mask in host byte order
+                * Get address and mask in host byte order for easy
+                * comparison as u_int32
                 */
-               addr = SRCADR(resaddr);
-               mask = SRCADR(resmask);
-               addr &= mask;           /* make sure low bits zero */
+               match.u.v4.addr = SRCADR(resaddr);
+               match.u.v4.mask = SRCADR(resmask);
+               match.u.v4.addr &= match.u.v4.mask;
 
+       } else if (IS_IPV6(resaddr)) {
+               v6 = 1;
                /*
-                * If this is the default address, point at first on
-                * list. Else go searching for it.
+                * Get address and mask in network byte order for easy
+                * comparison as byte sequences (e.g. memcmp())
                 */
-               if (addr == 0) {
-                       rlprev = 0;
-                       rl = restrictlist;
-               } else {
-                       rlprev = restrictlist;
-                       rl = rlprev->next;
-                       while (rl != 0) {
-                               if (rl->addr > addr) {
-                                       rl = 0;
-                                       break;
-                               } else if (rl->addr == addr) {
-                                       if (rl->mask == mask) {
-                                               if ((mflags &
-                                                   RESM_NTPONLY) ==
-                                                   (rl->mflags &
-                                                   RESM_NTPONLY))
-                                                       break;
-
-                                               if (!(mflags &
-                                                   RESM_NTPONLY)) {
-                                                       rl = 0;
-                                                       break;
-                                               }
-                                       } else if (rl->mask > mask) {
-                                               rl = 0;
-                                               break;
-                                       }
-                               }
-                               rlprev = rl;
-                               rl = rl->next;
-                       }
-               }
-       }
+               match.u.v6.mask = SOCK_ADDR6(resmask);
+               MASK_IPV6_ADDR(&match.u.v6.addr, PSOCK_ADDR6(resaddr),
+                              &match.u.v6.mask);
 
-       if (IS_IPV6(resaddr)) {
-               mask6 = SOCK_ADDR6(resmask);
-               SET_IPV6_ADDR_MASK(&addr6,
-                   PSOCK_ADDR6(resaddr), &mask6);
-               if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) {
-                       rlprev6 = NULL;
-                       rl6 = restrictlist6;
-               } else {
-                       rlprev6 = restrictlist6;
-                       rl6 = rlprev6->next;
-                       while (rl6 != 0) {
-                               addr_cmp = memcmp(&rl6->addr6, &addr6,
-                                   sizeof(addr6));
-                               if (addr_cmp > 0) {
-                                       rl6 = 0;
-                                       break;
-
-                               } else if (addr_cmp == 0) {
-                                       mask_cmp = memcmp(&rl6->mask6,
-                                           &mask6, sizeof(mask6));
-                                       if (mask_cmp == 0) {
-                                               if ((mflags &
-                                                   RESM_NTPONLY) ==
-                                                   (rl6->mflags &
-                                                   RESM_NTPONLY))
-                                                       break;
-
-                                               if (!(mflags &
-                                                   RESM_NTPONLY)) {
-                                                       rl6 = 0;
-                                                       break;
-                                               }
-                                       } else if (mask_cmp > 0) {
-                                               rl6 = 0;
-                                               break;
-                                       }
-                               }
-                               rlprev6 = rl6;
-                               rl6 = rl6->next;
-                       }
-               }
-       }
+       } else  /* not IPv4 nor IPv6 */
+               NTP_REQUIRE(0);
 
-       /*
-        * In case the above wasn't clear :-), either rl now points
-        * at the entry this call refers to, or rl is zero and rlprev
-        * points to the entry prior to where this one should go in
-        * the sort.
-        */
-       /*
-        * Switch based on operation
-        */
-       if (IS_IPV4(resaddr)) {
-               switch (op) {
-               case RESTRICT_FLAGS:
-
-                       /*
-                        * Here we add bits to the flags. If this is a
-                        * new restriction add it.
-                        */
-                       if (rl == 0) {
-                               if (numresfree == 0) {
-                                       rl = (struct restrictlist *)
-                                           emalloc(INCRESLIST *
-                                           sizeof(struct
-                                           restrictlist));
-                                       memset((char *)rl, 0,
-                                           INCRESLIST * sizeof(struct
-                                           restrictlist));
-                                       for (i = 0; i < INCRESLIST;
-                                           i++) {
-                                               rl->next = resfree;
-                                               resfree = rl;
-                                               rl++;
-                                       }
-                                       numresfree = INCRESLIST;
-                               }
-                               rl = resfree;
-                               resfree = rl->next;
-                               numresfree--;
-                               rl->addr = addr;
-                               rl->mask = mask;
-                               rl->mflags = (u_short)mflags;
-                               if (rlprev == NULL) {
-                                       rl->next = restrictlist;
-                                       restrictlist = rl;
-                               } else {
-                                       rl->next = rlprev->next;
-                                       rlprev->next = rl;
-                               }
-                               restrictcount++;
-                       }
-                       if ((rl->flags ^ (u_short)flags) &
-                           RES_LIMITED) {
-                               res_limited_refcnt++;
-                               mon_start(MON_RES);
-                       }
-                       rl->flags |= (u_short)flags;
-                       break;
+       match.flags = flags;
+       match.mflags = mflags;
+       res = match_restrict_entry(&match, v6);
 
-               case RESTRICT_UNFLAG:
-
-                       /*
-                        * Remove some bits from the flags. If we didn't
-                        * find this one, just return.
-                        */
-                       if (rl != 0) {
-                               if ((rl->flags ^ (u_short)flags) &
-                                   RES_LIMITED) {
-                                       res_limited_refcnt--;
-                                       if (res_limited_refcnt == 0)
-                                               mon_stop(MON_RES);
-                               }
-                               rl->flags &= (u_short)~flags;
-                       }
-                       break;
-       
-               case RESTRICT_REMOVE:
-               case RESTRICT_REMOVEIF:
-
-                       /*
-                        * Remove an entry from the table entirely if we
-                        * found one. Don't remove the default entry and
-                        * don't remove an interface entry.
-                        */
-                       if (rl != 0
-                           && rl->addr != htonl(INADDR_ANY)
-                           && !(rl->mflags & RESM_INTERFACE && op !=
-                           RESTRICT_REMOVEIF)) {
-                               if (rlprev != NULL) {
-                                       rlprev->next = rl->next;
-                               } else {
-                                       restrictlist = rl->next;
-                               }
-                               restrictcount--;
-                               if (rl->flags & RES_LIMITED) {
-                                       res_limited_refcnt--;
-                                       if (res_limited_refcnt == 0)
-                                               mon_stop(MON_RES);
-                               }
-                               memset((char *)rl, 0,
-                                   sizeof(struct restrictlist));
-
-                               rl->next = resfree;
-                               resfree = rl;
-                               numresfree++;
-                       }
-                       break;
+       switch (op) {
 
-               default:
-                       break;
-               }
-       } else if (IS_IPV6(resaddr)) {
-               switch (op) {
-               case RESTRICT_FLAGS:
-
-                       /*
-                        * Here we add bits to the flags. If this is a
-                        * new restriction add it.
-                        */
-                       if (rl6 == 0) {
-                               if (numresfree6 == 0) {
-                                       rl6 = (struct
-                                           restrictlist6 *)emalloc(
-                                           INCRESLIST * sizeof(struct
-                                           restrictlist6));
-                                       memset((char *)rl6, 0,
-                                           INCRESLIST * sizeof(struct
-                                           restrictlist6));
-
-                                       for (i = 0; i < INCRESLIST;
-                                           i++) {
-                                               rl6->next = resfree6;
-                                               resfree6 = rl6;
-                                               rl6++;
-                                       }
-                                       numresfree6 = INCRESLIST;
-                               }
-                               rl6 = resfree6;
-                               resfree6 = rl6->next;
-                               numresfree6--;
-                               rl6->addr6 = addr6;
-                               rl6->mask6 = mask6;
-                               rl6->mflags = (u_short)mflags;
-                               if (rlprev6 != NULL) {
-                                       rl6->next = rlprev6->next;
-                                       rlprev6->next = rl6;
-                               } else {
-                                       rl6->next = restrictlist6;
-                                       restrictlist6 = rl6;
-                               }
-                               restrictcount6++;
-                       }
-                       if ((rl6->flags ^ (u_short)flags) &
-                           RES_LIMITED) {
-                               res_limited_refcnt6++;
-                               mon_start(MON_RES);
-                       }
-                       rl6->flags |= (u_short)flags;
-                       break;
-
-               case RESTRICT_UNFLAG:
-
-                       /*
-                        * Remove some bits from the flags. If we didn't
-                        * find this one, just return.
-                        */
-                       if (rl6 != 0) {
-                               if ((rl6->flags ^ (u_short)flags) &
-                                   RES_LIMITED) {
-                                       res_limited_refcnt6--;
-                                       if (res_limited_refcnt6 == 0)
-                                               mon_stop(MON_RES);
-                               }
-                               rl6->flags &= (u_short)~flags;
-                       }
-                       break;
-
-               case RESTRICT_REMOVE:
-               case RESTRICT_REMOVEIF:
-
-                       /*
-                        * Remove an entry from the table entirely if we
-                        * found one. Don't remove the default entry and
-                        * don't remove an interface entry.
-                        */
-                       if (rl6 != 0 &&
-                           !IN6_IS_ADDR_UNSPECIFIED(&rl6->addr6)
-                           && !(rl6->mflags & RESM_INTERFACE && op !=
-                           RESTRICT_REMOVEIF)) {
-                               if (rlprev6 != NULL) {
-                                       rlprev6->next = rl6->next;
-                               } else {
-                                       restrictlist6 = rl6->next;
-                               }
-                               restrictcount6--;
-                               if (rl6->flags & RES_LIMITED) {
-                                       res_limited_refcnt6--;
-                                       if (res_limited_refcnt6 == 0)
-                                               mon_stop(MON_RES);
-                               }
-                               memset((char *)rl6, 0,
-                                   sizeof(struct restrictlist6));
-                               rl6->next = resfree6;
-                               resfree6 = rl6;
-                               numresfree6++;
+       case RESTRICT_FLAGS:
+               /*
+                * Here we add bits to the flags. If this is a
+                * new restriction add it.
+                */
+               if (NULL == res) {
+                       if (v6) {
+                               res = alloc_res6();
+                               memcpy(res, &match,
+                                      V6_SIZEOF_RESTRICT_U);
+                               plisthead = &restrictlist6;
+                       } else {
+                               res = alloc_res4();
+                               memcpy(res, &match,
+                                      V4_SIZEOF_RESTRICT_U);
+                               plisthead = &restrictlist4;
                        }
-                       break;
+                       LINK_SORT_SLIST(
+                               *plisthead, res,
+                               (v6)
+                                 ? res_sorts_before6(res, L_S_S_CUR())
+                                 : res_sorts_before4(res, L_S_S_CUR()),
+                               link, restrict_u);
+                       restrictcount++;
+                       if (RES_LIMITED & flags)
+                               inc_res_limited();
+               } else {
+                       if ((RES_LIMITED & flags) &&
+                           !(RES_LIMITED & res->flags))
+                               inc_res_limited();
+                       res->flags |= flags;
+               }
+               break;
 
-               default:
-                       break;
+       case RESTRICT_UNFLAG:
+               /*
+                * Remove some bits from the flags. If we didn't
+                * find this one, just return.
+                */
+               if (res != NULL) {
+                       if ((RES_LIMITED & res->flags)
+                           && (RES_LIMITED & flags))
+                               dec_res_limited();
+                       res->flags &= ~flags;
                }
+               break;
+
+       case RESTRICT_REMOVE:
+       case RESTRICT_REMOVEIF:
+               /*
+                * Remove an entry from the table entirely if we
+                * found one. Don't remove the default entry and
+                * don't remove an interface entry.
+                */
+               if (res != NULL
+                   && (RESTRICT_REMOVEIF == op
+                       || !(RESM_INTERFACE & res->mflags))
+                   && res != &restrict_def4
+                   && res != &restrict_def6)
+                       free_res(res, v6);
+               break;
+
+       default:        /* unknown op */
+               NTP_INSIST(0);
+               break;
        }
+
 }
+
index 16b8e7fe0c0e0453dfd87013ee2eebfc45a2d2cc..a906ae283d94e61bfdb61272b98d747df2f6c498 100644 (file)
@@ -58,7 +58,7 @@ struct timeval timeout = {0,0};
 #elif defined(SYS_WINNT)
 /*
  * Windows does not abort a select select call if SIGALRM goes off
- * so a 200 ms timeout is needed
+ * so a 200 ms timeout is needed (TIMER_HZ is 5).
  */
 struct sock_timeval timeout = {0,1000000/TIMER_HZ};
 #else
@@ -88,7 +88,7 @@ UINT wTimerRes;
 # define       NTPDATE_PRIO    (100)
 #endif
 
-#if defined(HAVE_TIMER_SETTIME) || defined (HAVE_TIMER_CREATE)
+#ifdef HAVE_TIMER_CREATE
 /* POSIX TIMERS - vxWorks doesn't have itimer - casey */
 static timer_t ntpdate_timerid;
 #endif
@@ -419,8 +419,18 @@ ntpdatemain (
                        } else {
                                sys_timeout = ((LFPTOFP(&tmp) * TIMER_HZ)
                                           + 0x8000) >> 16;
-                               if (sys_timeout == 0)
-                               sys_timeout = 1;
+                               /*
+                                * No less than 1s between requests to
+                                * a server to stay within ntpd's
+                                * default "discard minimum 1" (and 1s
+                                * enforcement slop).  That is enforced
+                                * only if the nondefault limited
+                                * restriction is in place, such as with
+                                * "restrict ... limited" and "restrict
+                                * ... kod limited".
+                                */
+                               if (MINTIMEOUT < sys_timeout)
+                                       sys_timeout = MINTIMEOUT;
                        }
                        break;
                case 'v':
@@ -828,6 +838,19 @@ receive(
        if (!is_authentic)
                server->trust |= 1;
 
+       /*
+        * Check for a KoD (rate limiting) response, cease and decist.
+        */
+       if (LEAP_NOTINSYNC == PKT_LEAP(rpkt->li_vn_mode) &&
+           STRATUM_PKT_UNSPEC == rpkt->stratum &&
+           !memcmp("RATE", &rpkt->refid, 4)) {
+               msyslog(LOG_ERR, "%s rate limit response from server.\n",
+                       stoa(&rbufp->recv_srcadr));
+               server->event_time = 0;
+               complete_servers++;
+               return;
+       }
+
        /*
         * Looks good.  Record info from the packet.
         */
@@ -845,8 +868,9 @@ receive(
         * Make sure the server is at least somewhat sane.      If not, try
         * again.
         */
-       if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) {
-               transmit(server);
+       if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)
+           || L_ISEQU(&rec, &server->org)) {
+               server->event_time = current_time + sys_timeout;
                return;
        }
 
@@ -895,10 +919,10 @@ receive(
        }
 
        /*
-        * Shift this data in, then transmit again.
+        * Shift this data in, then schedule another transmit.
         */
        server_data(server, (s_fp) di, &ci, 0);
-       transmit(server);
+       server->event_time = current_time + sys_timeout;
 }
 
 
@@ -1260,7 +1284,7 @@ clock_adjust(void)
                                lfptoa(&server->offset, 6));
                }
        } else {
-#if !defined SYS_WINNT && !defined SYS_CYGWIN32
+#ifndef SYS_WINNT
                if (simple_query || l_adj_systime(&server->offset)) {
                        msyslog(LOG_NOTICE, "adjust time server %s offset %s sec",
                                stoa(&server->srcadr),
@@ -1346,12 +1370,16 @@ addserver(
                        /* Name server is unusable. Exit after failing on the
                           first server, in order to shorten the timeout caused
                           by waiting for resolution of several servers */
-                       fprintf(stderr, "Name server cannot be used, exiting");
-                       msyslog(LOG_ERR, "name server cannot be used, reason: %s\n", gai_strerror(error));
+                       fprintf(stderr, "Exiting, name server cannot be used: %s (%d)",
+                               gai_strerror(error), error);
+                       msyslog(LOG_ERR, "name server cannot be used: %s (%d)\n",
+                               gai_strerror(error), error);
                        exit(1);
                }
-               fprintf(stderr, "Error : %s\n", gai_strerror(error));
-               msyslog(LOG_ERR, "can't find host %s\n", serv);
+               fprintf(stderr, "Error resolving %s: %s (%d)\n", serv,
+                       gai_strerror(error), error);
+               msyslog(LOG_ERR, "Can't find host %s: %s (%d)\n", serv,
+                       gai_strerror(error), error);
                return;
        }
 #ifdef DEBUG
@@ -1479,7 +1507,7 @@ alarming(
 {
        alarm_flag++;
 }
-#else
+#else  /* SYS_WINNT follows */
 void CALLBACK 
 alarming(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
 {
@@ -1505,16 +1533,14 @@ static void
 init_alarm(void)
 {
 #ifndef SYS_WINNT
-# ifndef HAVE_TIMER_SETTIME
-       struct itimerval itimer;
+# ifdef HAVE_TIMER_CREATE
+       struct itimerspec its;
 # else
-       struct itimerspec ntpdate_itimer;
+       struct itimerval itv;
 # endif
-#else
+#else  /* SYS_WINNT follows */
        TIMECAPS tc;
        UINT wTimerID;
-# endif /* SYS_WINNT */
-#if defined SYS_CYGWIN32 || defined SYS_WINNT
        HANDLE hToken;
        TOKEN_PRIVILEGES tkp;
        DWORD dwUser = 0;
@@ -1523,7 +1549,7 @@ init_alarm(void)
        alarm_flag = 0;
 
 #ifndef SYS_WINNT
-# if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)
+# ifdef HAVE_TIMER_CREATE
        alarm_flag = 0;
        /* this code was put in as setitimer() is non existant this us the
         * POSIX "equivalents" setup - casey
@@ -1545,44 +1571,26 @@ init_alarm(void)
         * Set up the alarm interrupt.  The first comes 1/(2*TIMER_HZ)
         * seconds from now and they continue on every 1/TIMER_HZ seconds.
         */
-       (void) signal_no_reset(SIGALRM, alarming);
-       ntpdate_itimer.it_interval.tv_sec = ntpdate_itimer.it_value.tv_sec = 0;
-       ntpdate_itimer.it_interval.tv_nsec = 1000000000/TIMER_HZ;
-       ntpdate_itimer.it_value.tv_nsec = 1000000000/(TIMER_HZ<<1);
-       timer_settime(ntpdate_timerid, 0 /* !TIMER_ABSTIME */, &ntpdate_itimer, NULL);
-# else
+       signal_no_reset(SIGALRM, alarming);
+       its.it_interval.tv_sec = 0;
+       its.it_value.tv_sec = 0;
+       its.it_interval.tv_nsec = 1000000000/TIMER_HZ;
+       its.it_value.tv_nsec = 1000000000/(TIMER_HZ<<1);
+       timer_settime(ntpdate_timerid, 0 /* !TIMER_ABSTIME */, &its, NULL);
+# else /* !HAVE_TIMER_CREATE follows */
        /*
         * Set up the alarm interrupt.  The first comes 1/(2*TIMER_HZ)
         * seconds from now and they continue on every 1/TIMER_HZ seconds.
         */
-       (void) signal_no_reset(SIGALRM, alarming);
-       itimer.it_interval.tv_sec = itimer.it_value.tv_sec = 0;
-       itimer.it_interval.tv_usec = 1000000/TIMER_HZ;
-       itimer.it_value.tv_usec = 1000000/(TIMER_HZ<<1);
-
-       setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
-# endif
-#if defined SYS_CYGWIN32
-       /*
-        * Get privileges needed for fiddling with the clock
-        */
-
-       /* get the current process token handle */
-       if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
-               msyslog(LOG_ERR, "OpenProcessToken failed: %m");
-               exit(1);
-       }
-       /* get the LUID for system-time privilege. */
-       LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);
-       tkp.PrivilegeCount = 1;         /* one privilege to set */
-       tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
-       /* get set-time privilege for this process. */
-       AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0);
-       /* cannot test return value of AdjustTokenPrivileges. */
-       if (GetLastError() != ERROR_SUCCESS)
-               msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m");
-#endif
-#else  /* SYS_WINNT */
+       signal_no_reset(SIGALRM, alarming);
+       itv.it_interval.tv_sec = 0;
+       itv.it_value.tv_sec = 0;
+       itv.it_interval.tv_usec = 1000000/TIMER_HZ;
+       itv.it_value.tv_usec = 1000000/(TIMER_HZ<<1);
+
+       setitimer(ITIMER_REAL, &itv, NULL);
+# endif        /* !HAVE_TIMER_CREATE */
+#else  /* SYS_WINNT follows */
        _tzset();
 
        /*
index 00bc3ff061d43eda082fb55d988a6cb6f717f061..75fba42910656ed693be3aabbeb131fb4a882a63 100644 (file)
@@ -91,7 +91,8 @@ struct server {
 /*
  * Some defaults
  */
-#define        DEFTIMEOUT      5               /* 5 timer increments */
+#define        MINTIMEOUT      (2 * TIMER_HZ)  /* 2s min. between packets */
+#define        DEFTIMEOUT      MINTIMEOUT      /*   (to the same server) */
 #define        DEFSAMPLES      4               /* get 4 samples per server */
 #define        DEFPRECISION    (-5)            /* the precision we claim */
 #define        DEFMAXPERIOD    60              /* maximum time to wait */
index 0d26a65c4bbdbf9687a6a3f15ceb3cd7d09034b0..b1d9a04299fc7ed7731a999aaa7da37f0ba15f27 100644 (file)
@@ -236,7 +236,7 @@ struct xcmd opcmds[] = {
 #ifdef ISC_PLATFORM_HAVESALEN
 #define SET_SS_LEN_IF_PRESENT(psau)                            \
        do {                                                    \
-               (psau)->sas.ss_len = SOCKLEN(psau);             \
+               (psau)->sa.sa_len = SOCKLEN(psau);              \
        } while (0)
 #else
 #define SET_SS_LEN_IF_PRESENT(psau)    do { } while (0)
@@ -841,8 +841,8 @@ again:
                        NSRCADR(&src) = pp->srcadr;
                }
 #ifdef ISC_PLATFORM_HAVESALEN
-               src.sas.ss_len = SOCKLEN(&src);
-               dst.sas.ss_len = SOCKLEN(&dst);
+               src.sa.sa_len = SOCKLEN(&src);
+               dst.sa.sa_len = SOCKLEN(&dst);
 #endif
                (void) fprintf(fp, "remote host:          %s\n",
                               nntohost(&src));
index a73585d1cb20e362c4c044fec308c8464885e18f..17992510bbd83e33223a871abe6f2ecdfaa96662 100644 (file)
@@ -148,7 +148,7 @@ recvdata (
 #ifdef DEBUG
        printf("sntp recvdata: Trying to receive data from...\n");
 #endif
-       slen = sizeof(sender->sas);
+       slen = sizeof(sender);
        recvc = recvfrom(rsock, rdata, rdata_length, 0, 
                         &sender->sa, &slen);
 #ifdef DEBUG
@@ -305,7 +305,7 @@ recv_bcst_data (
 
                default:
                {
-                       GETSOCKNAME_SOCKLEN_TYPE ss_len = sizeof(ras->sas);
+                       GETSOCKNAME_SOCKLEN_TYPE ss_len = sizeof(ras);
 
                        recv_bytes = recvfrom(rsock, rdata, rdata_len, 0, &ras->sa, &ss_len);
                }