]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
restrictions() must return restrict flags and ippeerlimit. Implement ippeerlimit.
authorHarlan Stenn <stenn@ntp.org>
Mon, 22 Jan 2018 10:55:41 +0000 (02:55 -0800)
committerHarlan Stenn <stenn@ntp.org>
Mon, 22 Jan 2018 10:55:41 +0000 (02:55 -0800)
bk: 5a65c32dr6iWPIzadIF-NgPCyN0R9Q

ChangeLog
include/ntp.h
include/ntpd.h
ntpd/ntp_config.c
ntpd/ntp_peer.c
ntpd/ntp_proto.c
ntpd/ntp_request.c
ntpd/ntp_restrict.c
ntpd/ntpsim.c
tests/ntpd/ntp_restrict.c

index 62c5f99e59dd0ee3e1fbef23d04c910157cedd9a..17e9243e5b941e1981aa5e9b3b796b312b578ae4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -85,6 +85,7 @@
 * Decode interface flags on receive() debug output.  HStenn.
 * Warn the user if deprecated "driftfile name WanderThreshold" is used.  HStenn.
 * Update the documentation in ntp.conf.def .  HStenn.
+* restrictions() must return restrict flags and ippeerlimit.  HStenn.
 
 ---
 (4.2.8p10) 2017/03/21 Released by Harlan Stenn <stenn@ntp.org>
index 3d56528cabac6a3088369734b8db1392dc89b5e0..deec0685181309e394d905f15dda4e05dd2a870a 100644 (file)
@@ -840,6 +840,12 @@ struct restrict_u_tag {
 #define        V6_SIZEOF_RESTRICT_U    (offsetof(restrict_u, u)        \
                                 + sizeof(res_addr6))
 
+typedef struct r4addr_tag      r4addr;
+struct r4addr_tag {
+       u_short         rflags;         /* match flags */
+       short           ippeerlimit;    /* IP peer limit */
+};
+
 char *build_iflags(u_int32 flags);
 char *build_mflags(u_short flags);
 char *build_rflags(u_short flags);
index 0de7f04e9dcfbc33d2c9ca572b64a989534f8468..f226f6448a7fd37f2fb241af5cd86c5b87534533 100644 (file)
@@ -172,15 +172,15 @@ extern    struct peer *findexistingpeer(sockaddr_u *, const char *,
 extern struct peer *findpeer   (struct recvbuf *, int, int *);
 extern struct peer *findpeerbyassoc(associd_t);
 extern  void   set_peerdstadr  (struct peer *, endpt *);
-extern struct peer *newpeer    (sockaddr_u *, const char *,
-                                endpt *, u_char, u_char,
-                                u_char, u_char, u_int, u_char, u_int32,
+extern struct peer *newpeer    (sockaddr_u *, const char *, endpt *,
+                                int, u_char, u_char, u_char, u_char,
+                                u_int, u_char, u_int32,
                                 keyid_t, const char *);
 extern void    peer_all_reset  (void);
 extern void    peer_clr_stats  (void);
-extern struct peer *peer_config(sockaddr_u *, const char *,
-                                endpt *, u_char, u_char,
-                                u_char, u_char, u_int, u_int32,
+extern struct peer *peer_config(sockaddr_u *, const char *, endpt *,
+                                int, u_char, u_char, u_char, u_char,
+                                u_int, u_int32,
                                 keyid_t, const char *);
 extern void    peer_reset      (struct peer *);
 extern void    refresh_all_peerinterfaces(void);
@@ -257,7 +257,7 @@ extern      void    reset_auth_stats(void);
 
 /* ntp_restrict.c */
 extern void    init_restrict   (void);
-extern u_short restrictions    (sockaddr_u *);
+extern void    restrictions    (sockaddr_u *, r4addr *);
 extern void    hack_restrict   (int, sockaddr_u *, sockaddr_u *,
                                 short, u_short, u_short, u_long);
 extern void    restrict_source (sockaddr_u *, int, u_long);
index de0433311cf024830c5b05acf312458fe1289d12..07d7b1c57c1622383db1cfb7d91d40e26ddbf4e3 100644 (file)
@@ -3978,6 +3978,9 @@ config_peers(
                 * If we have a numeric address, we can safely
                 * proceed in the mainline with it.  Otherwise, hand
                 * the hostname off to the blocking child.
+                *
+                * Note that if we're told to add the peer here, we
+                * do that regardless of ippeerlimit.
                 */
                if (is_ip_address(*cmdline_servers, AF_UNSPEC,
                                  &peeraddr)) {
@@ -3989,6 +3992,7 @@ config_peers(
                                        &peeraddr,
                                        NULL,
                                        NULL,
+                                       -1,
                                        MODE_CLIENT,
                                        NTP_VERSION,
                                        0,
@@ -4039,6 +4043,7 @@ config_peers(
                                &peeraddr,
                                curr_peer->addr->address,
                                NULL,
+                               -1,
                                hmode,
                                curr_peer->peerversion,
                                curr_peer->minpoll,
@@ -4062,6 +4067,7 @@ config_peers(
                                        &peeraddr,
                                        NULL,
                                        NULL,
+                                       -1,
                                        hmode,
                                        curr_peer->peerversion,
                                        curr_peer->minpoll,
@@ -4162,6 +4168,7 @@ peer_name_resolved(
                                &peeraddr,
                                NULL,
                                NULL,
+                               -1,
                                ctx->hmode,
                                ctx->version,
                                ctx->minpoll,
index ed7bd904e7cb16580bbf378d8a6982f3dc515ba1..f594ee950b3ce0db6ba8109f38dd2b5e7d5aa957 100644 (file)
@@ -568,6 +568,7 @@ peer_config(
        sockaddr_u *    srcadr,
        const char *    hostname,
        endpt *         dstadr,
+       int             ippeerlimit,
        u_char          hmode,
        u_char          version,
        u_char          minpoll,
@@ -618,7 +619,7 @@ peer_config(
                flags |= FLAG_IBURST;
        if ((MDF_ACAST | MDF_POOL) & cast_flags)
                flags &= ~FLAG_PREEMPT;
-       return newpeer(srcadr, hostname, dstadr, hmode, version,
+       return newpeer(srcadr, hostname, dstadr, ippeerlimit, hmode, version,
            minpoll, maxpoll, flags, cast_flags, ttl, key, ident);
 }
 
@@ -760,6 +761,7 @@ newpeer(
        sockaddr_u *    srcadr,
        const char *    hostname,
        endpt *         dstadr,
+       int             ippeerlimit,
        u_char          hmode,
        u_char          version,
        u_char          minpoll,
@@ -848,6 +850,18 @@ DPRINTF(1, ("newpeer(%s) found no existing and %d other associations\n",
                    : stoa(srcadr),
                ip_count));
 
+       /* Check ippeerlimit wrt ip_count */
+       if (ippeerlimit > -1) {
+               if (ip_count + 1 > ippeerlimit) {
+                       DPRINTF(2, ("newpeer(%s) denied - ippeerlimit %d\n",
+                               (hostname)
+                                   ? hostname
+                                   : stoa(srcadr),
+                               ippeerlimit));
+                       return NULL;
+               }
+       }
+
        /*
         * Allocate a new peer structure. Some dirt here, since some of
         * the initialization requires knowlege of our system state.
index c09d8f4da585605a798e27f04e7bc6d0797f35a5..9d99c88a47f84afad58017b91b6d8f279365ba93 100644 (file)
@@ -579,6 +579,7 @@ receive(
        u_char  hisleap;                /* packet leap indicator */
        u_char  hismode;                /* packet mode */
        u_char  hisstratum;             /* packet stratum */
+       r4addr  r4a;                    /* address restrictions */
        u_short restrict_mask;          /* restrict bits */
        const char *hm_str;             /* hismode string */
        const char *am_str;             /* association match string */
@@ -629,7 +630,9 @@ receive(
                sys_badlength++;
                return;                         /* bogus port */
        }
-       restrict_mask = restrictions(&rbufp->recv_srcadr);
+       restrictions(&rbufp->recv_srcadr, &r4a);
+       restrict_mask = r4a.rflags;
+
        pkt = &rbufp->recv_pkt;
        hisversion = PKT_VERSION(pkt->li_vn_mode);
        hisleap = PKT_LEAP(pkt->li_vn_mode);
@@ -1235,7 +1238,7 @@ receive(
                        sys_declined++;
                        return;                 /* no help */
                }
-               peer = newpeer(&rbufp->recv_srcadr, NULL, rbufp->dstadr,
+               peer = newpeer(&rbufp->recv_srcadr, NULL, rbufp->dstadr, -1,
                               MODE_CLIENT, hisversion, peer2->minpoll,
                               peer2->maxpoll, FLAG_PREEMPT |
                               (FLAG_IBURST & peer2->flags), MDF_UCAST |
@@ -1356,10 +1359,9 @@ receive(
                         * Do not execute the volley. Start out in
                         * broadcast client mode.
                         */
-                       peer = newpeer(&rbufp->recv_srcadr, NULL,
-                           match_ep, MODE_BCLIENT, hisversion,
-                           pkt->ppoll, pkt->ppoll, FLAG_PREEMPT,
-                           MDF_BCLNT, 0, skeyid, sys_ident);
+                       peer = newpeer(&rbufp->recv_srcadr, NULL, match_ep, -1,
+                           MODE_BCLIENT, hisversion, pkt->ppoll, pkt->ppoll,
+                           FLAG_PREEMPT, MDF_BCLNT, 0, skeyid, sys_ident);
                        if (NULL == peer) {
                                DPRINTF(2, ("receive: AM_NEWBCL drop: duplicate\n"));
                                sys_restricted++;
@@ -1380,7 +1382,7 @@ receive(
                 * packet, normally 6 (64 s) and that the poll interval
                 * is fixed at this value.
                 */
-               peer = newpeer(&rbufp->recv_srcadr, NULL, match_ep,
+               peer = newpeer(&rbufp->recv_srcadr, NULL, match_ep, -1,
                    MODE_CLIENT, hisversion, pkt->ppoll, pkt->ppoll,
                    FLAG_BC_VOL | FLAG_IBURST | FLAG_PREEMPT, MDF_BCLNT,
                    0, skeyid, sys_ident);
@@ -1481,12 +1483,13 @@ receive(
 
                /*
                 * The message is correctly authenticated and allowed.
-                * Mobilize a symmetric passive association.
+                * Mobilize a symmetric passive association, if we won't
+                * exceed the ippeerlimit.
                 */
-               if ((peer = newpeer(&rbufp->recv_srcadr, NULL,
-                   rbufp->dstadr, MODE_PASSIVE, hisversion, pkt->ppoll,
-                   NTP_MAXDPOLL, 0, MDF_UCAST, 0, skeyid,
-                   sys_ident)) == NULL) {
+               if ((peer = newpeer(&rbufp->recv_srcadr, NULL, rbufp->dstadr,
+                                   -1, MODE_PASSIVE, hisversion, pkt->ppoll,
+                                   NTP_MAXDPOLL, 0, MDF_UCAST, 0, skeyid,
+                                   sys_ident)) == NULL) {
                        DPRINTF(2, ("receive: AM_NEWPASS drop: newpeer() failed\n"));
                        sys_declined++;
                        return;                 /* ignore duplicate */
@@ -4408,6 +4411,7 @@ pool_xmit(
        int                     rc;
        struct interface *      lcladr;
        sockaddr_u *            rmtadr;
+       r4addr                  r4a;
        int                     restrict_mask;
        struct peer *           p;
        l_fp                    xmt_tx;
@@ -4448,7 +4452,8 @@ pool_xmit(
        } while (p != NULL && pool->ai != NULL);
        if (p != NULL)
                return; /* out of addresses, re-query DNS next poll */
-       restrict_mask = restrictions(rmtadr);
+       restrictions(rmtadr, &r4a);
+       restrict_mask = r4a.rflags;
        if (RES_FLAGS & restrict_mask)
                restrict_source(rmtadr, 0,
                                current_time + POOL_SOLICIT_WINDOW + 1);
index 1636fdc35d065edc79d18a6341d269158aa7a204..6cdb1f440d4ee977c7f395f2c44a94b3a0909a66 100644 (file)
@@ -1369,10 +1369,13 @@ do_conf(
                 *
                 *   - minpoll/maxpoll, but they are treated properly
                 *     for all cases internally. Checking not necessary.
+                *
+                * Note that we ignore any previously-specified ippeerlimit.
+                * If we're told to create the peer, we create the peer.
                 */
                
                /* finally create the peer */
-               if (peer_config(&peeraddr, NULL, NULL,
+               if (peer_config(&peeraddr, NULL, NULL, -1,
                    temp_cp.hmode, temp_cp.version, temp_cp.minpoll, 
                    temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid,
                    NULL) == 0)
index abf9e2cd2760edef83968cc2e0671396bfab333e..49b68b5fb712433c10d4ae37b4bf1be3751949bf 100644 (file)
@@ -411,19 +411,23 @@ res_sorts_before6(
 
 
 /*
- * restrictions - return restrictions for this host
+ * restrictions - return restrictions for this host in *r4a
  */
-u_short
+void
 restrictions(
-       sockaddr_u *srcadr
+       sockaddr_u *srcadr,
+       r4addr *r4a
        )
 {
        restrict_u *match;
        struct in6_addr *pin6;
-       u_short flags;
+
+       REQUIRE(NULL != r4a);
 
        res_calls++;
-       flags = 0;
+       r4a->rflags = RES_IGNORE;
+       r4a->ippeerlimit = 0;
+
        /* IPv4 source address */
        if (IS_IPV4(srcadr)) {
                /*
@@ -432,7 +436,7 @@ restrictions(
                 * not later!)
                 */
                if (IN_CLASSD(SRCADR(srcadr)))
-                       return (int)RES_IGNORE;
+                       return;
 
                match = match_restrict4_addr(SRCADR(srcadr),
                                             SRCPORT(srcadr));
@@ -449,7 +453,8 @@ restrictions(
                        res_not_found++;
                else
                        res_found++;
-               flags = match->flags;
+               r4a->rflags = match->flags;
+               r4a->ippeerlimit = match->ippeerlimit;
        }
 
        /* IPv6 source address */
@@ -462,7 +467,7 @@ restrictions(
                 * not later!)
                 */
                if (IN6_IS_ADDR_MULTICAST(pin6))
-                       return (int)RES_IGNORE;
+                       return;
 
                match = match_restrict6_addr(pin6, SRCPORT(srcadr));
                INSIST(match != NULL);
@@ -471,9 +476,10 @@ restrictions(
                        res_not_found++;
                else
                        res_found++;
-               flags = match->flags;
+               r4a->rflags = match->flags;
+               r4a->ippeerlimit = match->ippeerlimit;
        }
-       return (flags);
+       return;
 }
 
 
index b7c3218fc1a2ac531f14913e837983af7fe053db..5ae05b7ab0c9f1cc5269b05c5a5d66ef018c121e 100644 (file)
@@ -79,6 +79,7 @@ void create_server_associations(void)
                                NULL,
                                loopback_interface,
                                MODE_CLIENT,
+                               -1,
                                NTP_VERSION,
                                NTP_MINDPOLL,
                                NTP_MAXDPOLL,
index ea1a25d0a281095892a81b48fe4ae4be701bb8b9..1420323db413ad24d54a970ec8159a9344cf9a44 100644 (file)
@@ -92,10 +92,11 @@ void test_ReturnsCorrectDefaultRestrictions(void)
 {
        sockaddr_u sockaddr = create_sockaddr_u(AF_INET,
                54321, "63.161.169.137");
+       r4addr  r4a;
 
-       u_short retval = restrictions(&sockaddr);
+       restrictions(&sockaddr, &r4a);
 
-       TEST_ASSERT_EQUAL(0, retval);
+       TEST_ASSERT_EQUAL(0, r4a.rflags);
 }
 
 
@@ -108,6 +109,7 @@ void test_HackingDefaultRestriction(void)
        */
 
        const u_short flags = 42;
+       r4addr r4a;
 
        sockaddr_u resaddr = create_sockaddr_u(AF_INET,
                54321, "0.0.0.0");
@@ -119,7 +121,8 @@ void test_HackingDefaultRestriction(void)
        sockaddr_u sockaddr = create_sockaddr_u(AF_INET,
                54321, "111.123.251.124");
 
-       TEST_ASSERT_EQUAL(flags, restrictions(&sockaddr));
+       restrictions(&sockaddr, &r4a);
+       TEST_ASSERT_EQUAL(flags, r4a.rflags);
 }
 
 
@@ -128,10 +131,12 @@ void test_CantRemoveDefaultEntry(void)
 {
        sockaddr_u resaddr = create_sockaddr_u(AF_INET, 54321, "0.0.0.0");
        sockaddr_u resmask = create_sockaddr_u(AF_INET, 54321, "0.0.0.0");
+       r4addr r4a;
 
        hack_restrict(RESTRICT_REMOVE, &resaddr, &resmask, -1, 0, 0, 0);
 
-       TEST_ASSERT_EQUAL(0, restrictions(&resaddr));
+       restrictions(&resaddr, &r4a);
+       TEST_ASSERT_EQUAL(0, r4a.rflags);
 }
 
 
@@ -140,12 +145,14 @@ void test_AddingNewRestriction(void)
 {
        sockaddr_u resaddr = create_sockaddr_u(AF_INET, 54321, "11.22.33.44");
        sockaddr_u resmask = create_sockaddr_u(AF_INET, 54321, "128.0.0.0");
+       r4addr r4a;
 
        const u_short flags = 42;
 
        hack_restrict(RESTRICT_FLAGS, &resaddr, &resmask, -1, 0, flags, 0);
 
-       TEST_ASSERT_EQUAL(flags, restrictions(&resaddr));
+       restrictions(&resaddr, &r4a);
+       TEST_ASSERT_EQUAL(flags, r4a.rflags);
 }
 
 
@@ -163,12 +170,14 @@ void test_TheMostFittingRestrictionIsMatched(void)
        /* it also matches, but we prefer the one above, as it's more specific */
        sockaddr_u resaddr_second_match = create_sockaddr_u(AF_INET, 54321, "11.99.33.44");
        sockaddr_u resmask_second_match = create_sockaddr_u(AF_INET, 54321, "255.0.0.0");
+       r4addr r4a;
 
        hack_restrict(RESTRICT_FLAGS, &resaddr_not_matching, &resmask_not_matching, -1, 0, 11, 0);
        hack_restrict(RESTRICT_FLAGS, &resaddr_best_match, &resmask_best_match, -1, 0, 22, 0);
        hack_restrict(RESTRICT_FLAGS, &resaddr_second_match, &resmask_second_match, -1, 0, 128, 0);
 
-       TEST_ASSERT_EQUAL(22, restrictions(&resaddr_target));
+       restrictions(&resaddr_target, &r4a);
+       TEST_ASSERT_EQUAL(22, r4a.rflags);
 }
 
 
@@ -185,6 +194,7 @@ void test_DeletedRestrictionIsNotMatched(void)
 
        sockaddr_u resaddr_second_match = create_sockaddr_u(AF_INET, 54321, "11.99.33.44");
        sockaddr_u resmask_second_match = create_sockaddr_u(AF_INET, 54321, "255.0.0.0");
+       r4addr r4a;
 
        hack_restrict(RESTRICT_FLAGS, &resaddr_not_matching, &resmask_not_matching, -1, 0, 11, 0);
        hack_restrict(RESTRICT_FLAGS, &resaddr_best_match, &resmask_best_match, -1, 0, 22, 0);
@@ -193,7 +203,8 @@ void test_DeletedRestrictionIsNotMatched(void)
        /* deleting the best match*/
        hack_restrict(RESTRICT_REMOVE, &resaddr_best_match, &resmask_best_match, -1, 0, 22, 0);
 
-       TEST_ASSERT_EQUAL(128, restrictions(&resaddr_target));
+       restrictions(&resaddr_target, &r4a);
+       TEST_ASSERT_EQUAL(128, r4a.rflags);
 }
 
 
@@ -202,10 +213,12 @@ void test_RestrictUnflagWorks(void)
 {
        sockaddr_u resaddr = create_sockaddr_u(AF_INET, 54321, "11.22.30.20");
        sockaddr_u resmask = create_sockaddr_u(AF_INET, 54321, "255.255.0.0");
+       r4addr r4a;
 
        hack_restrict(RESTRICT_FLAGS, &resaddr, &resmask, -1, 0, 11, 0);
 
        hack_restrict(RESTRICT_UNFLAG, &resaddr, &resmask, -1, 0, 10, 0);
 
-       TEST_ASSERT_EQUAL(1, restrictions(&resaddr));
+       restrictions(&resaddr, &r4a);
+       TEST_ASSERT_EQUAL(1, r4a.rflags);
 }