Annotation of embedaddon/ntp/ntpd/ntp_peer.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * ntp_peer.c - management of data maintained for peer associations
                      3:  */
                      4: #ifdef HAVE_CONFIG_H
                      5: #include <config.h>
                      6: #endif
                      7: 
                      8: #include <stdio.h>
                      9: #include <sys/types.h>
                     10: 
                     11: #include "ntpd.h"
                     12: #include "ntp_lists.h"
                     13: #include "ntp_stdlib.h"
                     14: #include "ntp_control.h"
                     15: #include <ntp_random.h>
                     16: #ifdef OPENSSL
                     17: #include "openssl/rand.h"
                     18: #endif /* OPENSSL */
                     19: 
                     20: #ifdef SYS_WINNT
                     21: int accept_wildcard_if_for_winnt;
                     22: #else
                     23: const int accept_wildcard_if_for_winnt = FALSE;
                     24: #endif
                     25: 
                     26: /*
                     27:  *                  Table of valid association combinations
                     28:  *                  ---------------------------------------
                     29:  *
                     30:  *                             packet->mode
                     31:  * peer->mode      | UNSPEC  ACTIVE PASSIVE  CLIENT  SERVER  BCAST
                     32:  * ----------      | ---------------------------------------------
                     33:  * NO_PEER         |   e       1       0       1       1       1
                     34:  * ACTIVE          |   e       1       1       0       0       0
                     35:  * PASSIVE         |   e       1       e       0       0       0
                     36:  * CLIENT          |   e       0       0       0       1       0
                     37:  * SERVER          |   e       0       0       0       0       0
                     38:  * BCAST           |   e       0       0       0       0       0
                     39:  * BCLIENT         |   e       0       0       0       e       1
                     40:  *
                     41:  * One point to note here: a packet in BCAST mode can potentially match
                     42:  * a peer in CLIENT mode, but we that is a special case and we check for
                     43:  * that early in the decision process.  This avoids having to keep track
                     44:  * of what kind of associations are possible etc...  We actually
                     45:  * circumvent that problem by requiring that the first b(m)roadcast
                     46:  * received after the change back to BCLIENT mode sets the clock.
                     47:  */
                     48: #define AM_MODES       7       /* number of rows and columns */
                     49: #define NO_PEER                0       /* action when no peer is found */
                     50: 
                     51: int AM[AM_MODES][AM_MODES] = {
                     52: /*     { UNSPEC,   ACTIVE,     PASSIVE,    CLIENT,     SERVER,     BCAST } */
                     53: 
                     54: /*NONE*/{ AM_ERR, AM_NEWPASS, AM_NOMATCH, AM_FXMIT,   AM_MANYCAST, AM_NEWBCL},
                     55: 
                     56: /*A*/  { AM_ERR, AM_PROCPKT, AM_PROCPKT, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
                     57: 
                     58: /*P*/  { AM_ERR, AM_PROCPKT, AM_ERR,     AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
                     59: 
                     60: /*C*/  { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT,  AM_NOMATCH},
                     61: 
                     62: /*S*/  { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
                     63: 
                     64: /*BCST*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
                     65: 
                     66: /*BCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_PROCPKT},
                     67: };
                     68: 
                     69: #define MATCH_ASSOC(x, y)      AM[(x)][(y)]
                     70: 
                     71: /*
                     72:  * These routines manage the allocation of memory to peer structures
                     73:  * and the maintenance of the peer hash table. The three main entry
                     74:  * points are findpeer(), which looks for matching peer structures in
                     75:  * the peer list, newpeer(), which allocates a new peer structure and
                     76:  * adds it to the list, and unpeer(), which demobilizes the association
                     77:  * and deallocates the structure.
                     78:  */
                     79: /*
                     80:  * Peer hash tables
                     81:  */
                     82: struct peer *peer_hash[NTP_HASH_SIZE]; /* peer hash table */
                     83: int    peer_hash_count[NTP_HASH_SIZE]; /* peers in each bucket */
                     84: struct peer *assoc_hash[NTP_HASH_SIZE];        /* association ID hash table */
                     85: int    assoc_hash_count[NTP_HASH_SIZE]; /* peers in each bucket */
                     86: static struct peer *peer_free;         /* peer structures free list */
                     87: int    peer_free_count;                /* count of free structures */
                     88: 
                     89: /*
                     90:  * Association ID.  We initialize this value randomly, then assign a new
                     91:  * value every time the peer structure is incremented.
                     92:  */
                     93: static associd_t current_association_ID; /* association ID */
                     94: 
                     95: /*
                     96:  * Memory allocation watermarks.
                     97:  */
                     98: #define        INIT_PEER_ALLOC         15      /* initialize for 15 peers */
                     99: #define        INC_PEER_ALLOC          5       /* when run out, add 5 more */
                    100: 
                    101: /*
                    102:  * Miscellaneous statistic counters which may be queried.
                    103:  */
                    104: u_long peer_timereset;                 /* time stat counters zeroed */
                    105: u_long findpeer_calls;                 /* calls to findpeer */
                    106: u_long assocpeer_calls;                /* calls to findpeerbyassoc */
                    107: u_long peer_allocations;               /* allocations from free list */
                    108: u_long peer_demobilizations;           /* structs freed to free list */
                    109: int    total_peer_structs;             /* peer structs */
                    110: int    peer_associations;              /* mobilized associations */
                    111: int    peer_preempt;                   /* preemptable associations */
                    112: static struct peer init_peer_alloc[INIT_PEER_ALLOC]; /* init alloc */
                    113: 
                    114: static void        getmorepeermem       (void);
                    115: static struct interface *select_peerinterface (struct peer *, sockaddr_u *, struct interface *, u_char);
                    116: 
                    117: static int score(struct peer *);
                    118: 
                    119: /*
                    120:  * init_peer - initialize peer data structures and counters
                    121:  *
                    122:  * N.B. We use the random number routine in here. It had better be
                    123:  * initialized prior to getting here.
                    124:  */
                    125: void
                    126: init_peer(void)
                    127: {
                    128:        register int i;
                    129: 
                    130:        /*
                    131:         * Clear hash tables and counters.
                    132:         */
                    133:        memset(peer_hash, 0, sizeof(peer_hash));
                    134:        memset(peer_hash_count, 0, sizeof(peer_hash_count));
                    135:        memset(assoc_hash, 0, sizeof(assoc_hash));
                    136:        memset(assoc_hash_count, 0, sizeof(assoc_hash_count));
                    137: 
                    138:        /*
                    139:         * Clear stat counters
                    140:         */
                    141:        findpeer_calls = peer_allocations = 0;
                    142:        assocpeer_calls = peer_demobilizations = 0;
                    143: 
                    144:        /*
                    145:         * Initialize peer memory.
                    146:         */
                    147:        peer_free = NULL;
                    148:        for (i = 0; i < INIT_PEER_ALLOC; i++)
                    149:                LINK_SLIST(peer_free, &init_peer_alloc[i], next);
                    150:        total_peer_structs = INIT_PEER_ALLOC;
                    151:        peer_free_count = INIT_PEER_ALLOC;
                    152: 
                    153:        /*
                    154:         * Initialize our first association ID
                    155:         */
                    156:        while ((current_association_ID = ntp_random() & 0xffff) == 0);
                    157: }
                    158: 
                    159: 
                    160: /*
                    161:  * getmorepeermem - add more peer structures to the free list
                    162:  */
                    163: static void
                    164: getmorepeermem(void)
                    165: {
                    166:        register int i;
                    167:        register struct peer *peer;
                    168: 
                    169:        peer = (struct peer *)emalloc(INC_PEER_ALLOC *
                    170:            sizeof(struct peer));
                    171:        for (i = 0; i < INC_PEER_ALLOC; i++) {
                    172:                LINK_SLIST(peer_free, peer, next);
                    173:                peer++;
                    174:        }
                    175: 
                    176:        total_peer_structs += INC_PEER_ALLOC;
                    177:        peer_free_count += INC_PEER_ALLOC;
                    178: }
                    179: 
                    180: 
                    181: /*
                    182:  * findexistingpeer - return a pointer to a peer in the hash table
                    183:  */
                    184: struct peer *
                    185: findexistingpeer(
                    186:        sockaddr_u *    addr,
                    187:        struct peer *   start_peer,
                    188:        int             mode,
                    189:        u_char          cast_flags
                    190:        )
                    191: {
                    192:        register struct peer *peer;
                    193: 
                    194:        /*
                    195:         * start_peer is included so we can locate instances of the
                    196:         * same peer through different interfaces in the hash table.
                    197:         * Without MDF_BCLNT, a match requires the same mode and remote
                    198:         * address.  MDF_BCLNT associations start out as MODE_CLIENT
                    199:         * if broadcastdelay is not specified, and switch to
                    200:         * MODE_BCLIENT after estimating the one-way delay.  Duplicate
                    201:         * associations are expanded in definition to match any other
                    202:         * MDF_BCLNT with the same srcadr (remote, unicast address).
                    203:         */
                    204:        if (NULL == start_peer)
                    205:                peer = peer_hash[NTP_HASH_ADDR(addr)];
                    206:        else
                    207:                peer = start_peer->next;
                    208:        
                    209:        while (peer != NULL) {
                    210:                if (ADDR_PORT_EQ(addr, &peer->srcadr)
                    211:                    && (-1 == mode || peer->hmode == mode ||
                    212:                        ((MDF_BCLNT & peer->cast_flags) &&
                    213:                         (MDF_BCLNT & cast_flags))))
                    214:                        break;
                    215:                peer = peer->next;
                    216:        }
                    217: 
                    218:        return peer;
                    219: }
                    220: 
                    221: 
                    222: /*
                    223:  * findpeer - find and return a peer match for a received datagram in
                    224:  *           the peer_hash table.
                    225:  */
                    226: struct peer *
                    227: findpeer(
                    228:        struct recvbuf *rbufp,
                    229:        int             pkt_mode,
                    230:        int *           action
                    231:        )
                    232: {
                    233:        struct peer *   p;
                    234:        sockaddr_u *    srcadr;
                    235:        u_int           hash;
                    236:        struct pkt *    pkt;
                    237:        l_fp            pkt_org;
                    238: 
                    239:        findpeer_calls++;
                    240:        srcadr = &rbufp->recv_srcadr;
                    241:        hash = NTP_HASH_ADDR(srcadr);
                    242:        for (p = peer_hash[hash]; p != NULL; p = p->next) {
                    243:                if (SOCK_EQ(srcadr, &p->srcadr) &&
                    244:                    NSRCPORT(srcadr) == NSRCPORT(&p->srcadr)) {
                    245: 
                    246:                        /*
                    247:                         * if the association matching rules determine
                    248:                         * that this is not a valid combination, then
                    249:                         * look for the next valid peer association.
                    250:                         */
                    251:                        *action = MATCH_ASSOC(p->hmode, pkt_mode);
                    252: 
                    253:                        /*
                    254:                         * A response to our manycastclient solicitation
                    255:                         * might be misassociated with an ephemeral peer
                    256:                         * already spun for the server.  If the packet's
                    257:                         * org timestamp doesn't match the peer's, check
                    258:                         * if it matches the ACST prototype peer's.  If
                    259:                         * so it is a redundant solicitation response,
                    260:                         * return AM_ERR to discard it.  [Bug 1762]
                    261:                         */
                    262:                        if (MODE_SERVER == pkt_mode &&
                    263:                            AM_PROCPKT == *action) {
                    264:                                pkt = &rbufp->recv_pkt;
                    265:                                NTOHL_FP(&pkt->org, &pkt_org);
                    266:                                if (!L_ISEQU(&p->aorg, &pkt_org) &&
                    267:                                    findmanycastpeer(rbufp))
                    268:                                        *action = AM_ERR;
                    269:                        }
                    270: 
                    271:                        /*
                    272:                         * if an error was returned, exit back right
                    273:                         * here.
                    274:                         */
                    275:                        if (*action == AM_ERR)
                    276:                                return NULL;
                    277: 
                    278:                        /*
                    279:                         * if a match is found, we stop our search.
                    280:                         */
                    281:                        if (*action != AM_NOMATCH)
                    282:                                break;
                    283:                }
                    284:        }
                    285: 
                    286:        /*
                    287:         * If no matching association is found
                    288:         */
                    289:        if (NULL == p) {
                    290:                *action = MATCH_ASSOC(NO_PEER, pkt_mode);
                    291:        } else if (p->dstadr != rbufp->dstadr) {
                    292:                set_peerdstadr(p, rbufp->dstadr);
                    293:                if (p->dstadr == rbufp->dstadr) {
                    294:                        DPRINTF(1, ("Changed %s local address to match response\n",
                    295:                                    stoa(&p->srcadr)));
                    296:                        return findpeer(rbufp, pkt_mode, action);
                    297:                }
                    298:        }
                    299:        return p;
                    300: }
                    301: 
                    302: /*
                    303:  * findpeerbyassocid - find and return a peer using his association ID
                    304:  */
                    305: struct peer *
                    306: findpeerbyassoc(
                    307:        u_int assoc
                    308:        )
                    309: {
                    310:        struct peer *p;
                    311:        u_int hash;
                    312: 
                    313:        assocpeer_calls++;
                    314: 
                    315:        hash = assoc & NTP_HASH_MASK;
                    316:        for (p = assoc_hash[hash]; p != NULL; p = p->ass_next) {
                    317:                if (assoc == p->associd)
                    318:                        return p;
                    319:        }
                    320:        return NULL;
                    321: }
                    322: 
                    323: 
                    324: /*
                    325:  * clear_all - flush all time values for all associations
                    326:  */
                    327: void
                    328: clear_all(void)
                    329: {
                    330:        struct peer *peer, *next_peer;
                    331:        int n;
                    332: 
                    333:        /*
                    334:         * This routine is called when the clock is stepped, and so all
                    335:         * previously saved time values are untrusted.
                    336:         */
                    337:        for (n = 0; n < NTP_HASH_SIZE; n++) {
                    338:                for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
                    339:                        next_peer = peer->next;
                    340:                        if (!(peer->cast_flags & (MDF_ACAST |
                    341:                            MDF_MCAST | MDF_BCAST))) {
                    342:                                peer_clear(peer, "STEP");
                    343:                        }
                    344:                }
                    345:        }
                    346: #ifdef DEBUG
                    347:        if (debug)
                    348:                printf("clear_all: at %lu\n", current_time);
                    349: #endif
                    350: }
                    351: 
                    352: 
                    353: /*
                    354:  * score_all() - determine if an association can be demobilized
                    355:  */
                    356: int
                    357: score_all(
                    358:        struct peer *peer       /* peer structure pointer */
                    359:        )
                    360: {
                    361:        struct peer *speer, *next_peer;
                    362:        int     n;
                    363:        int     temp, tamp;
                    364: 
                    365:        /*
                    366:         * This routine finds the minimum score for all ephemeral
                    367:         * assocations and returns > 0 if the association can be
                    368:         * demobilized.
                    369:         */
                    370:        tamp = score(peer);
                    371:        temp = 100;
                    372:        for (n = 0; n < NTP_HASH_SIZE; n++) {
                    373:                for (speer = peer_hash[n]; speer != 0; speer =
                    374:                    next_peer) {
                    375:                        int     x;
                    376: 
                    377:                        next_peer = speer->next;
                    378:                        if ((x = score(speer)) < temp && (peer->flags &
                    379:                            FLAG_PREEMPT))
                    380:                                temp = x;
                    381:                }
                    382:        }
                    383: #ifdef DEBUG
                    384:        if (debug)
                    385:                printf("score_all: at %lu score %d min %d\n",
                    386:                    current_time, tamp, temp);
                    387: #endif
                    388:        if (tamp != temp)
                    389:                temp = 0;
                    390:        return (temp);
                    391: }
                    392: 
                    393: 
                    394: /*
                    395:  * score() - calculate preemption score
                    396:  */
                    397: static int
                    398: score(
                    399:        struct peer *peer       /* peer structure pointer */
                    400:        )
                    401: {
                    402:        int     temp;
                    403: 
                    404:        /*
                    405:         * This routine calculates the premption score from the peer
                    406:         * error bits and status. Increasing values are more cherished.
                    407:         */
                    408:        temp = 0;
                    409:        if (!(peer->flash & TEST10))
                    410:                temp++;                 /* 1 good synch and stratum */
                    411:        if (!(peer->flash & TEST13))
                    412:                temp++;                 /* 2 reachable */
                    413:        if (!(peer->flash & TEST12))
                    414:                temp++;                 /* 3 no loop */
                    415:        if (!(peer->flash & TEST11))
                    416:                temp++;                 /* 4 good distance */
                    417:        if (peer->status >= CTL_PST_SEL_SELCAND)
                    418:                temp++;                 /* 5 in the hunt */
                    419:        if (peer->status != CTL_PST_SEL_EXCESS)
                    420:                temp++;                 /* 6 not spare tire */
                    421:        return (temp);                  /* selection status */
                    422: }
                    423: 
                    424: 
                    425: /*
                    426:  * unpeer - remove peer structure from hash table and free structure
                    427:  */
                    428: void
                    429: unpeer(
                    430:        struct peer *peer_to_remove
                    431:        )
                    432: {
                    433:        register struct peer *unlinked;
                    434:        int     hash;
                    435:        char    tbuf[80];
                    436: 
                    437:        snprintf(tbuf, sizeof(tbuf), "assoc %d",
                    438:            peer_to_remove->associd);
                    439:        report_event(PEVNT_DEMOBIL, peer_to_remove, tbuf);
                    440:        set_peerdstadr(peer_to_remove, NULL);
                    441:        hash = NTP_HASH_ADDR(&peer_to_remove->srcadr);
                    442:        peer_hash_count[hash]--;
                    443:        peer_demobilizations++;
                    444:        peer_associations--;
                    445:        if (peer_to_remove->flags & FLAG_PREEMPT)
                    446:                peer_preempt--;
                    447: #ifdef REFCLOCK
                    448:        /*
                    449:         * If this peer is actually a clock, shut it down first
                    450:         */
                    451:        if (peer_to_remove->flags & FLAG_REFCLOCK)
                    452:                refclock_unpeer(peer_to_remove);
                    453: #endif
                    454:        peer_to_remove->action = 0;     /* disable timeout actions */
                    455: 
                    456:        UNLINK_SLIST(unlinked, peer_hash[hash], peer_to_remove, next,
                    457:            struct peer);
                    458: 
                    459:        if (NULL == unlinked) {
                    460:                peer_hash_count[hash]++;
                    461:                msyslog(LOG_ERR, "peer struct for %s not in table!",
                    462:                    stoa(&peer_to_remove->srcadr));
                    463:        }
                    464: 
                    465:        /*
                    466:         * Remove him from the association hash as well.
                    467:         */
                    468:        hash = peer_to_remove->associd & NTP_HASH_MASK;
                    469:        assoc_hash_count[hash]--;
                    470: 
                    471:        UNLINK_SLIST(unlinked, assoc_hash[hash], peer_to_remove,
                    472:            ass_next, struct peer);
                    473: 
                    474:        if (NULL == unlinked) {
                    475:                assoc_hash_count[hash]++;
                    476:                msyslog(LOG_ERR,
                    477:                    "peer struct for %s not in association table!",
                    478:                    stoa(&peer_to_remove->srcadr));
                    479:        }
                    480: 
                    481:        LINK_SLIST(peer_free, peer_to_remove, next);
                    482:        peer_free_count++;
                    483: }
                    484: 
                    485: 
                    486: /*
                    487:  * peer_config - configure a new association
                    488:  */
                    489: struct peer *
                    490: peer_config(
                    491:        sockaddr_u *srcadr,
                    492:        struct interface *dstadr,
                    493:        int hmode,
                    494:        int version,
                    495:        int minpoll,
                    496:        int maxpoll,
                    497:        u_int flags,
                    498:        int ttl,
                    499:        keyid_t key,
                    500:        u_char *keystr
                    501:        )
                    502: {
                    503:        u_char cast_flags;
                    504: 
                    505:        /*
                    506:         * We do a dirty little jig to figure the cast flags. This is
                    507:         * probably not the best place to do this, at least until the
                    508:         * configure code is rebuilt. Note only one flag can be set.
                    509:         */
                    510:        switch (hmode) {
                    511:        case MODE_BROADCAST:
                    512:                if (IS_MCAST(srcadr))
                    513:                        cast_flags = MDF_MCAST;
                    514:                else
                    515:                        cast_flags = MDF_BCAST;
                    516:                break;
                    517: 
                    518:        case MODE_CLIENT:
                    519:                if (IS_MCAST(srcadr))
                    520:                        cast_flags = MDF_ACAST;
                    521:                else
                    522:                        cast_flags = MDF_UCAST;
                    523:                break;
                    524: 
                    525:        default:
                    526:                cast_flags = MDF_UCAST;
                    527:        }
                    528: 
                    529:        /*
                    530:         * Mobilize the association and initialize its variables. If
                    531:         * emulating ntpdate, force iburst.
                    532:         */
                    533:        if (mode_ntpdate)
                    534:                flags |= FLAG_IBURST;
                    535:        return(newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll,
                    536:            flags | FLAG_CONFIG, cast_flags, ttl, key));
                    537: }
                    538: 
                    539: /*
                    540:  * setup peer dstadr field keeping it in sync with the interface
                    541:  * structures
                    542:  */
                    543: void
                    544: set_peerdstadr(
                    545:        struct peer *   p,
                    546:        endpt *         dstadr
                    547:        )
                    548: {
                    549:        struct peer *   unlinked;
                    550: 
                    551:        if (p->dstadr == dstadr)
                    552:                return;
                    553: 
                    554:        /*
                    555:         * Don't accept updates to a separate multicast receive-only
                    556:         * endpt while a BCLNT peer is running its unicast protocol.
                    557:         */
                    558:        if (dstadr != NULL && (FLAG_BC_VOL & p->flags) &&
                    559:            (INT_MCASTIF & dstadr->flags) && MODE_CLIENT == p->hmode) {
                    560:                return;
                    561:        }
                    562:        if (p->dstadr != NULL) {
                    563:                p->dstadr->peercnt--;
                    564:                UNLINK_SLIST(unlinked, p->dstadr->peers, p, ilink,
                    565:                             struct peer);
                    566:                msyslog(LOG_INFO, "%s interface %s -> %s",
                    567:                        stoa(&p->srcadr), stoa(&p->dstadr->sin),
                    568:                        (dstadr != NULL)
                    569:                            ? stoa(&dstadr->sin)
                    570:                            : "(none)");
                    571:        }
                    572:        p->dstadr = dstadr;
                    573:        if (dstadr != NULL) {
                    574:                LINK_SLIST(dstadr->peers, p, ilink);
                    575:                dstadr->peercnt++;
                    576:        }
                    577: }
                    578: 
                    579: /*
                    580:  * attempt to re-rebind interface if necessary
                    581:  */
                    582: static void
                    583: peer_refresh_interface(
                    584:        struct peer *peer
                    585:        )
                    586: {
                    587:        endpt * niface;
                    588:        endpt * piface;
                    589: 
                    590:        niface = select_peerinterface(peer, &peer->srcadr, NULL,
                    591:                                      peer->cast_flags);
                    592: 
                    593:        DPRINTF(4, (
                    594:            "peer_refresh_interface: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x: new interface: ",
                    595:            peer->dstadr == NULL ? "<null>" :
                    596:            stoa(&peer->dstadr->sin), stoa(&peer->srcadr),
                    597:            peer->hmode, peer->version, peer->minpoll,
                    598:            peer->maxpoll, peer->flags, peer->cast_flags,
                    599:            peer->ttl, peer->keyid));
                    600:        if (niface != NULL) {
                    601:                DPRINTF(4, (
                    602:                    "fd=%d, bfd=%d, name=%.16s, flags=0x%x, ifindex=%u, sin=%s",
                    603:                    niface->fd,  niface->bfd, niface->name,
                    604:                    niface->flags, niface->ifindex,
                    605:                    stoa(&niface->sin)));
                    606:                if (niface->flags & INT_BROADCAST)
                    607:                        DPRINTF(4, (", bcast=%s",
                    608:                                stoa(&niface->bcast)));
                    609:                DPRINTF(4, (", mask=%s\n", stoa(&niface->mask)));
                    610:        } else {
                    611:                DPRINTF(4, ("<NONE>\n"));
                    612:        }
                    613: 
                    614:        piface = peer->dstadr;
                    615:        set_peerdstadr(peer, niface);
                    616:        if (peer->dstadr) {
                    617:                /*
                    618:                 * clear crypto if we change the local address
                    619:                 */
                    620:                if (peer->dstadr != piface && !(peer->cast_flags &
                    621:                    MDF_ACAST) && peer->pmode != MODE_BROADCAST)
                    622:                        peer_clear(peer, "XFAC");
                    623: 
                    624:                /*
                    625:                 * Broadcast needs the socket enabled for broadcast
                    626:                 */
                    627:                if (peer->cast_flags & MDF_BCAST) {
                    628:                        enable_broadcast(peer->dstadr, &peer->srcadr);
                    629:                }
                    630: 
                    631:                /*
                    632:                 * Multicast needs the socket interface enabled for
                    633:                 * multicast
                    634:                 */
                    635:                if (peer->cast_flags & MDF_MCAST) {
                    636:                        enable_multicast_if(peer->dstadr,
                    637:                            &peer->srcadr);
                    638:                }
                    639:        }
                    640: }
                    641: 
                    642: /*
                    643:  * refresh_all_peerinterfaces - see that all interface bindings are up
                    644:  * to date
                    645:  */
                    646: void
                    647: refresh_all_peerinterfaces(void)
                    648: {
                    649:        struct peer *peer, *next_peer;
                    650:        int n;
                    651: 
                    652:        /*
                    653:         * this is called when the interface list has changed
                    654:         * give all peers a chance to find a better interface
                    655:         */
                    656:        for (n = 0; n < NTP_HASH_SIZE; n++) {
                    657:                for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
                    658:                        next_peer = peer->next;
                    659:                        peer_refresh_interface(peer);
                    660:                }
                    661:        }
                    662: }
                    663: 
                    664:        
                    665: /*
                    666:  * find an interface suitable for the src address
                    667:  */
                    668: static endpt *
                    669: select_peerinterface(
                    670:        struct peer *   peer,
                    671:        sockaddr_u *    srcadr,
                    672:        endpt *         dstadr,
                    673:        u_char          cast_flags
                    674:        )
                    675: {
                    676:        endpt *ep;
                    677:        endpt *wild;
                    678: 
                    679:        wild = ANY_INTERFACE_CHOOSE(srcadr);
                    680: 
                    681:        /*
                    682:         * Initialize the peer structure and dance the interface jig.
                    683:         * Reference clocks step the loopback waltz, the others
                    684:         * squaredance around the interface list looking for a buddy. If
                    685:         * the dance peters out, there is always the wildcard interface.
                    686:         * This might happen in some systems and would preclude proper
                    687:         * operation with public key cryptography.
                    688:         */
                    689:        if (ISREFCLOCKADR(srcadr)) {
                    690:                ep = loopback_interface;
                    691:        } else if (cast_flags & 
                    692:                   (MDF_BCLNT | MDF_ACAST | MDF_MCAST | MDF_BCAST)) {
                    693:                ep = findbcastinter(srcadr);
                    694:                if (ep != NULL)
                    695:                        DPRINTF(4, ("Found *-cast interface %s for address %s\n",
                    696:                                stoa(&ep->sin), stoa(srcadr)));
                    697:                else
                    698:                        DPRINTF(4, ("No *-cast local address found for address %s\n",
                    699:                                stoa(srcadr)));
                    700:        } else {
                    701:                ep = dstadr;
                    702:                if (NULL == ep)
                    703:                        ep = wild;
                    704:        } 
                    705:        /*
                    706:         * If it is a multicast address, findbcastinter() may not find
                    707:         * it.  For unicast, we get to find the interface when dstadr is
                    708:         * given to us as the wildcard (ANY_INTERFACE_CHOOSE).  Either
                    709:         * way, try a little harder.
                    710:         */
                    711:        if (wild == ep)
                    712:                ep = findinterface(srcadr);
                    713:        /*
                    714:         * we do not bind to the wildcard interfaces for output 
                    715:         * as our (network) source address would be undefined and
                    716:         * crypto will not work without knowing the own transmit address
                    717:         */
                    718:        if (ep != NULL && INT_WILDCARD & ep->flags)
                    719:                if (!accept_wildcard_if_for_winnt)  
                    720:                        ep = NULL;
                    721: 
                    722:        return ep;
                    723: }
                    724: 
                    725: /*
                    726:  * newpeer - initialize a new peer association
                    727:  */
                    728: struct peer *
                    729: newpeer(
                    730:        sockaddr_u *srcadr,
                    731:        struct interface *dstadr,
                    732:        int     hmode,
                    733:        int     version,
                    734:        int     minpoll,
                    735:        int     maxpoll,
                    736:        u_int   flags,
                    737:        u_char  cast_flags,
                    738:        int     ttl,
                    739:        keyid_t key
                    740:        )
                    741: {
                    742:        struct peer *peer;
                    743:        u_int   hash;
                    744:        char    tbuf[80];
                    745: 
                    746: #ifdef OPENSSL
                    747:        /*
                    748:         * If Autokey is requested but not configured, complain loudly.
                    749:         */
                    750:        if (!crypto_flags) {
                    751:                if (key > NTP_MAXKEY) {
                    752:                        return (NULL);
                    753: 
                    754:                } else if (flags & FLAG_SKEY) {
                    755:                        msyslog(LOG_ERR, "Autokey not configured");
                    756:                        return (NULL);
                    757:                } 
                    758:        }
                    759: #endif /* OPENSSL */
                    760: 
                    761:        /*
                    762:         * First search from the beginning for an association with given
                    763:         * remote address and mode. If an interface is given, search
                    764:         * from there to find the association which matches that
                    765:         * destination. If the given interface is "any", track down the
                    766:         * actual interface, because that's what gets put into the peer
                    767:         * structure.
                    768:         */
                    769:        if (dstadr != NULL) {
                    770:                peer = findexistingpeer(srcadr, NULL, hmode, cast_flags);
                    771:                while (peer != NULL) {
                    772:                        if (peer->dstadr == dstadr ||
                    773:                            ((MDF_BCLNT & cast_flags) &&
                    774:                             (MDF_BCLNT & peer->cast_flags)))
                    775:                                break;
                    776: 
                    777:                        if (dstadr == ANY_INTERFACE_CHOOSE(srcadr) &&
                    778:                            peer->dstadr == findinterface(srcadr))
                    779:                                break;
                    780: 
                    781:                        peer = findexistingpeer(srcadr, peer, hmode,
                    782:                                                cast_flags);
                    783:                }
                    784:        } else {
                    785:                /* no endpt address given */
                    786:                peer = findexistingpeer(srcadr, NULL, hmode, cast_flags);
                    787:        }
                    788: 
                    789:        /*
                    790:         * If a peer is found, this would be a duplicate and we don't
                    791:         * allow that. This avoids duplicate ephemeral (broadcast/
                    792:         * multicast) and preemptible (manycast and pool) client
                    793:         * associations.
                    794:         */
                    795:        if (peer != NULL)
                    796:                return (NULL);
                    797: 
                    798:        /*
                    799:         * Allocate a new peer structure. Some dirt here, since some of
                    800:         * the initialization requires knowlege of our system state.
                    801:         */
                    802:        if (peer_free_count == 0)
                    803:                getmorepeermem();
                    804:        UNLINK_HEAD_SLIST(peer, peer_free, next);
                    805:        peer_free_count--;
                    806:        peer_associations++;
                    807:        if (flags & FLAG_PREEMPT)
                    808:                peer_preempt++;
                    809:        memset(peer, 0, sizeof(*peer));
                    810: 
                    811:        /*
                    812:         * Assign an association ID and increment the system variable.
                    813:         */
                    814:        peer->associd = current_association_ID;
                    815:        if (++current_association_ID == 0)
                    816:                ++current_association_ID;
                    817: 
                    818:        DPRINTF(3, ("newpeer: cast flags: 0x%x for address: %s\n",
                    819:                    cast_flags, stoa(srcadr)));
                    820: 
                    821:        peer->srcadr = *srcadr;
                    822:        set_peerdstadr(peer, select_peerinterface(peer, srcadr, dstadr,
                    823:            cast_flags));
                    824:        peer->hmode = (u_char)hmode;
                    825:        peer->version = (u_char)version;
                    826:        peer->flags = flags;
                    827: 
                    828:        /*
                    829:         * It is an error to set minpoll less than NTP_MINPOLL or to
                    830:         * set maxpoll greater than NTP_MAXPOLL. However, minpoll is
                    831:         * clamped not greater than NTP_MAXPOLL and maxpoll is clamped
                    832:         * not less than NTP_MINPOLL without complaint. Finally,
                    833:         * minpoll is clamped not greater than maxpoll.
                    834:         */
                    835:        if (minpoll == 0)
                    836:                peer->minpoll = NTP_MINDPOLL;
                    837:        else
                    838:                peer->minpoll = (u_char)min(minpoll, NTP_MAXPOLL);
                    839:        if (maxpoll == 0)
                    840:                peer->maxpoll = NTP_MAXDPOLL;
                    841:        else
                    842:                peer->maxpoll = (u_char)max(maxpoll, NTP_MINPOLL);
                    843:        if (peer->minpoll > peer->maxpoll)
                    844:                peer->minpoll = peer->maxpoll;
                    845: 
                    846:        if (peer->dstadr)
                    847:                DPRINTF(3, ("newpeer: using fd %d and our addr %s\n",
                    848:                            peer->dstadr->fd, stoa(&peer->dstadr->sin)));
                    849:        else
                    850:                DPRINTF(3, ("newpeer: local interface currently not bound\n")); 
                    851: 
                    852:        /*
                    853:         * Broadcast needs the socket enabled for broadcast
                    854:         */
                    855:        if ((cast_flags & MDF_BCAST) && peer->dstadr)
                    856:                enable_broadcast(peer->dstadr, srcadr);
                    857: 
                    858:        /*
                    859:         * Multicast needs the socket interface enabled for multicast
                    860:         */
                    861:        if ((cast_flags & MDF_MCAST) && peer->dstadr)
                    862:                enable_multicast_if(peer->dstadr, srcadr);
                    863: 
                    864: #ifdef OPENSSL
                    865:        if (key > NTP_MAXKEY)
                    866:                peer->flags |= FLAG_SKEY;
                    867: #endif /* OPENSSL */
                    868:        peer->cast_flags = cast_flags;
                    869:        peer->ttl = (u_char)ttl;
                    870:        peer->keyid = key;
                    871:        peer->precision = sys_precision;
                    872:        peer->hpoll = peer->minpoll;
                    873:        if (cast_flags & MDF_ACAST)
                    874:                peer_clear(peer, "ACST");
                    875:        else if (cast_flags & MDF_MCAST)
                    876:                peer_clear(peer, "MCST");
                    877:        else if (cast_flags & MDF_BCAST)
                    878:                peer_clear(peer, "BCST");
                    879:        else
                    880:                peer_clear(peer, "INIT");
                    881:        if (mode_ntpdate)
                    882:                peer_ntpdate++;
                    883: 
                    884:        /*
                    885:         * Note time on statistics timers.
                    886:         */
                    887:        peer->timereset = current_time;
                    888:        peer->timereachable = current_time;
                    889:        peer->timereceived = current_time;
                    890: 
                    891: #ifdef REFCLOCK
                    892:        if (ISREFCLOCKADR(&peer->srcadr)) {
                    893: 
                    894:                /*
                    895:                 * We let the reference clock support do clock
                    896:                 * dependent initialization.  This includes setting
                    897:                 * the peer timer, since the clock may have requirements
                    898:                 * for this.
                    899:                 */
                    900:                if (maxpoll == 0)
                    901:                        peer->maxpoll = peer->minpoll;
                    902:                if (!refclock_newpeer(peer)) {
                    903:                        /*
                    904:                         * Dump it, something screwed up
                    905:                         */
                    906:                        set_peerdstadr(peer, NULL);
                    907:                        LINK_SLIST(peer_free, peer, next);
                    908:                        peer_free_count++;
                    909:                        return (NULL);
                    910:                }
                    911:        }
                    912: #endif
                    913: 
                    914:        /*
                    915:         * Put the new peer in the hash tables.
                    916:         */
                    917:        hash = NTP_HASH_ADDR(&peer->srcadr);
                    918:        LINK_SLIST(peer_hash[hash], peer, next);
                    919:        peer_hash_count[hash]++;
                    920:        hash = peer->associd & NTP_HASH_MASK;
                    921:        LINK_SLIST(assoc_hash[hash], peer, ass_next);
                    922:        assoc_hash_count[hash]++;
                    923:        snprintf(tbuf, sizeof(tbuf), "assoc %d", peer->associd);
                    924:        report_event(PEVNT_MOBIL, peer, tbuf);
                    925:        DPRINTF(1, ("newpeer: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x\n",
                    926:            peer->dstadr == NULL ? "<null>" : stoa(&peer->dstadr->sin),
                    927:            stoa(&peer->srcadr), peer->hmode, peer->version,
                    928:            peer->minpoll, peer->maxpoll, peer->flags, peer->cast_flags,
                    929:            peer->ttl, peer->keyid));
                    930:        return (peer);
                    931: }
                    932: 
                    933: 
                    934: /*
                    935:  * peer_clr_stats - clear peer module statiistics counters
                    936:  */
                    937: void
                    938: peer_clr_stats(void)
                    939: {
                    940:        findpeer_calls = 0;
                    941:        assocpeer_calls = 0;
                    942:        peer_allocations = 0;
                    943:        peer_demobilizations = 0;
                    944:        peer_timereset = current_time;
                    945: }
                    946: 
                    947: /*
                    948:  * peer_reset - reset statistics counters
                    949:  */
                    950: void
                    951: peer_reset(
                    952:        struct peer *peer
                    953:        )
                    954: {
                    955:        if (peer == NULL)
                    956:                return;
                    957: 
                    958:        peer->timereset = current_time;
                    959:        peer->sent = 0;
                    960:        peer->received = 0;
                    961:        peer->processed = 0;
                    962:        peer->badauth = 0;
                    963:        peer->bogusorg = 0;
                    964:        peer->oldpkt = 0;
                    965:        peer->seldisptoolarge = 0;
                    966:        peer->selbroken = 0;
                    967: }
                    968: 
                    969: 
                    970: /*
                    971:  * peer_all_reset - reset all peer statistics counters
                    972:  */
                    973: void
                    974: peer_all_reset(void)
                    975: {
                    976:        struct peer *peer;
                    977:        int hash;
                    978: 
                    979:        for (hash = 0; hash < NTP_HASH_SIZE; hash++)
                    980:            for (peer = peer_hash[hash]; peer != 0; peer = peer->next)
                    981:                peer_reset(peer);
                    982: }
                    983: 
                    984: 
                    985: /*
                    986:  * findmanycastpeer - find and return a manycast peer
                    987:  */
                    988: struct peer *
                    989: findmanycastpeer(
                    990:        struct recvbuf *rbufp   /* receive buffer pointer */
                    991:        )
                    992: {
                    993:        register struct peer *peer;
                    994:        struct pkt *pkt;
                    995:        l_fp p_org;
                    996:        int i;
                    997: 
                    998:        /*
                    999:         * This routine is called upon arrival of a server-mode message
                   1000:         * from a manycast client. Search the peer list for a manycast
                   1001:         * client association where the last transmit timestamp matches
                   1002:         * the originate timestamp. This assumes the transmit timestamps
                   1003:         * for possibly more than one manycast association are unique.
                   1004:         */
                   1005:        pkt = &rbufp->recv_pkt;
                   1006:        for (i = 0; i < NTP_HASH_SIZE; i++) {
                   1007:                if (peer_hash_count[i] == 0)
                   1008:                        continue;
                   1009: 
                   1010:                for (peer = peer_hash[i]; peer != 0; peer =
                   1011:                    peer->next) {
                   1012:                        if (peer->cast_flags & MDF_ACAST) {
                   1013:                                NTOHL_FP(&pkt->org, &p_org);
                   1014:                                if (L_ISEQU(&p_org, &peer->aorg))
                   1015:                                        return (peer);
                   1016:                        }
                   1017:                }
                   1018:        }
                   1019:        return (NULL);
                   1020: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>