Annotation of embedaddon/ntp/ntpd/ntp_io.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * ntp_io.c - input/output routines for ntpd.  The socket-opening code
        !             3:  *                was shamelessly stolen from ntpd.
        !             4:  */
        !             5: 
        !             6: #ifdef HAVE_CONFIG_H
        !             7: # include <config.h>
        !             8: #endif
        !             9: 
        !            10: #include <stdio.h>
        !            11: #include <signal.h>
        !            12: #ifdef HAVE_SYS_PARAM_H
        !            13: # include <sys/param.h>
        !            14: #endif
        !            15: #ifdef HAVE_SYS_IOCTL_H
        !            16: # include <sys/ioctl.h>
        !            17: #endif
        !            18: #ifdef HAVE_SYS_SOCKIO_H       /* UXPV: SIOC* #defines (Frank Vance <fvance@waii.com>) */
        !            19: # include <sys/sockio.h>
        !            20: #endif
        !            21: #ifdef HAVE_SYS_UIO_H
        !            22: # include <sys/uio.h>
        !            23: #endif
        !            24: 
        !            25: #include "ntp_machine.h"
        !            26: #include "ntpd.h"
        !            27: #include "ntp_io.h"
        !            28: #include "iosignal.h"
        !            29: #include "ntp_lists.h"
        !            30: #include "ntp_refclock.h"
        !            31: #include "ntp_stdlib.h"
        !            32: #include "ntp_request.h"
        !            33: #include "ntp.h"
        !            34: #include "ntp_unixtime.h"
        !            35: #include "ntp_assert.h"
        !            36: #include "ntpd-opts.h"
        !            37: 
        !            38: /* Don't include ISC's version of IPv6 variables and structures */
        !            39: #define ISC_IPV6_H 1
        !            40: #include <isc/mem.h>
        !            41: #include <isc/interfaceiter.h>
        !            42: #include <isc/netaddr.h>
        !            43: #include <isc/result.h>
        !            44: #include <isc/sockaddr.h>
        !            45: 
        !            46: #ifdef SIM
        !            47: #include "ntpsim.h"
        !            48: #endif
        !            49: 
        !            50: #ifdef HAS_ROUTING_SOCKET
        !            51: # include <net/route.h>
        !            52: # ifdef HAVE_RTNETLINK
        !            53: #  include <linux/rtnetlink.h>
        !            54: # endif
        !            55: #endif
        !            56: 
        !            57: 
        !            58: /*
        !            59:  * setsockopt does not always have the same arg declaration
        !            60:  * across all platforms. If it's not defined we make it empty
        !            61:  */
        !            62: 
        !            63: #ifndef SETSOCKOPT_ARG_CAST
        !            64: #define SETSOCKOPT_ARG_CAST
        !            65: #endif
        !            66: 
        !            67: extern int listen_to_virtual_ips;
        !            68: 
        !            69: /*
        !            70:  * NIC rule entry
        !            71:  */
        !            72: typedef struct nic_rule_tag nic_rule;
        !            73: 
        !            74: struct nic_rule_tag {
        !            75:        nic_rule *      next;
        !            76:        nic_rule_action action;
        !            77:        nic_rule_match  match_type;
        !            78:        char *          if_name;
        !            79:        sockaddr_u      addr;
        !            80:        int             prefixlen;
        !            81: };
        !            82: 
        !            83: /*
        !            84:  * NIC rule listhead.  Entries are added at the head so that the first
        !            85:  * match in the list is the last matching rule specified.
        !            86:  */
        !            87: nic_rule *nic_rule_list;
        !            88: 
        !            89: 
        !            90: #if defined(SO_TIMESTAMP) && defined(SCM_TIMESTAMP)
        !            91: #if defined(CMSG_FIRSTHDR)
        !            92: #define HAVE_TIMESTAMP
        !            93: #define USE_TIMESTAMP_CMSG
        !            94: #ifndef TIMESTAMP_CTLMSGBUF_SIZE
        !            95: #define TIMESTAMP_CTLMSGBUF_SIZE 1536 /* moderate default */
        !            96: #endif
        !            97: #else
        !            98: /* fill in for old/other timestamp interfaces */
        !            99: #endif
        !           100: #endif
        !           101: 
        !           102: #if defined(SYS_WINNT)
        !           103: #include <transmitbuff.h>
        !           104: #include <isc/win32os.h>
        !           105: /*
        !           106:  * Windows C runtime ioctl() can't deal properly with sockets, 
        !           107:  * map to ioctlsocket for this source file.
        !           108:  */
        !           109: #define ioctl(fd, opt, val)  ioctlsocket((fd), (opt), (u_long *)(val))
        !           110: #endif  /* SYS_WINNT */
        !           111: 
        !           112: /*
        !           113:  * We do asynchronous input using the SIGIO facility.  A number of
        !           114:  * recvbuf buffers are preallocated for input. In the signal
        !           115:  * handler we poll to see which sockets are ready and read the
        !           116:  * packets from them into the recvbuf's along with a time stamp and
        !           117:  * an indication of the source host and the interface it was received
        !           118:  * through.  This allows us to get as accurate receive time stamps
        !           119:  * as possible independent of other processing going on.
        !           120:  *
        !           121:  * We watch the number of recvbufs available to the signal handler
        !           122:  * and allocate more when this number drops below the low water
        !           123:  * mark.  If the signal handler should run out of buffers in the
        !           124:  * interim it will drop incoming frames, the idea being that it is
        !           125:  * better to drop a packet than to be inaccurate.
        !           126:  */
        !           127: 
        !           128: 
        !           129: /*
        !           130:  * Other statistics of possible interest
        !           131:  */
        !           132: volatile u_long packets_dropped;       /* total number of packets dropped on reception */
        !           133: volatile u_long packets_ignored;       /* packets received on wild card interface */
        !           134: volatile u_long packets_received;      /* total number of packets received */
        !           135:         u_long packets_sent;           /* total number of packets sent */
        !           136:         u_long packets_notsent;        /* total number of packets which couldn't be sent */
        !           137: 
        !           138: volatile u_long handler_calls; /* number of calls to interrupt handler */
        !           139: volatile u_long handler_pkts;  /* number of pkts received by handler */
        !           140: u_long io_timereset;           /* time counters were reset */
        !           141: 
        !           142: /*
        !           143:  * Interface stuff
        !           144:  */
        !           145: endpt *        any_interface;          /* wildcard ipv4 interface */
        !           146: endpt *        any6_interface;         /* wildcard ipv6 interface */
        !           147: endpt *        loopback_interface;     /* loopback ipv4 interface */
        !           148: 
        !           149: isc_boolean_t broadcast_client_enabled;        /* is broadcast client enabled */
        !           150: int ninterfaces;                       /* Total number of interfaces */
        !           151: 
        !           152: int disable_dynamic_updates;           /* scan interfaces once only */
        !           153: 
        !           154: #ifdef REFCLOCK
        !           155: /*
        !           156:  * Refclock stuff.     We keep a chain of structures with data concerning
        !           157:  * the guys we are doing I/O for.
        !           158:  */
        !           159: static struct refclockio *refio;
        !           160: #endif /* REFCLOCK */
        !           161: 
        !           162: #if defined(HAVE_IPTOS_SUPPORT)
        !           163: /* set IP_TOS to minimize packet delay */
        !           164: # if defined(IPTOS_PREC_INTERNETCONTROL)
        !           165:        unsigned int qos = IPTOS_PREC_INTERNETCONTROL;
        !           166: # else
        !           167:         unsigned int qos = IPTOS_LOWDELAY;
        !           168: # endif
        !           169: #endif
        !           170: 
        !           171: /*
        !           172:  * File descriptor masks etc. for call to select
        !           173:  * Not needed for I/O Completion Ports
        !           174:  */
        !           175: fd_set activefds;
        !           176: int maxactivefd;
        !           177: /*
        !           178:  * bit alternating value to detect verified interfaces during an update cycle
        !           179:  */
        !           180: static  u_short                sys_interphase = 0;
        !           181: 
        !           182: static endpt * new_interface(endpt *);
        !           183: static void    add_interface(endpt *);
        !           184: static int     update_interfaces(u_short, interface_receiver_t,
        !           185:                                  void *);
        !           186: static void    remove_interface(endpt *);
        !           187: static endpt * create_interface(u_short, endpt *);
        !           188: 
        !           189: static int     move_fd                 (SOCKET);
        !           190: static int     is_wildcard_addr        (const sockaddr_u *);
        !           191: 
        !           192: /*
        !           193:  * Multicast functions
        !           194:  */
        !           195: static isc_boolean_t   addr_ismulticast        (sockaddr_u *);
        !           196: static isc_boolean_t   is_anycast              (sockaddr_u *,
        !           197:                                                 const char *);
        !           198: 
        !           199: /*
        !           200:  * Not all platforms support multicast
        !           201:  */
        !           202: #ifdef MCAST
        !           203: static isc_boolean_t   socket_multicast_enable (endpt *, sockaddr_u *);
        !           204: static isc_boolean_t   socket_multicast_disable(endpt *, sockaddr_u *);
        !           205: #endif
        !           206: 
        !           207: #ifdef DEBUG
        !           208: static void interface_dump     (const endpt *);
        !           209: static void sockaddr_dump      (const sockaddr_u *);
        !           210: static void print_interface    (const endpt *, char *, char *);
        !           211: #define DPRINT_INTERFACE(level, args) do { if (debug >= (level)) { print_interface args; } } while (0)
        !           212: #else
        !           213: #define DPRINT_INTERFACE(level, args) do {} while (0)
        !           214: #endif
        !           215: 
        !           216: typedef struct vsock vsock_t;
        !           217: enum desc_type { FD_TYPE_SOCKET, FD_TYPE_FILE };
        !           218: 
        !           219: struct vsock {
        !           220:        vsock_t *       link;
        !           221:        SOCKET          fd;
        !           222:        enum desc_type  type;
        !           223: };
        !           224: 
        !           225: vsock_t        *fd_list;
        !           226: 
        !           227: #if !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET)
        !           228: /*
        !           229:  * async notification processing (e. g. routing sockets)
        !           230:  */
        !           231: /*
        !           232:  * support for receiving data on fd that is not a refclock or a socket
        !           233:  * like e. g. routing sockets
        !           234:  */
        !           235: struct asyncio_reader {
        !           236:        struct asyncio_reader *link;                /* the list this is being kept in */
        !           237:        SOCKET fd;                                  /* fd to be read */
        !           238:        void  *data;                                /* possibly local data */
        !           239:        void (*receiver)(struct asyncio_reader *);  /* input handler */
        !           240: };
        !           241: 
        !           242: struct asyncio_reader *asyncio_reader_list;
        !           243: 
        !           244: static void delete_asyncio_reader (struct asyncio_reader *);
        !           245: static struct asyncio_reader *new_asyncio_reader (void);
        !           246: static void add_asyncio_reader (struct asyncio_reader *, enum desc_type);
        !           247: static void remove_asyncio_reader (struct asyncio_reader *);
        !           248: 
        !           249: #endif /* !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) */
        !           250: 
        !           251: static void init_async_notifications (void);
        !           252: 
        !           253: static int     addr_eqprefix   (const sockaddr_u *, const sockaddr_u *,
        !           254:                                 int);
        !           255: static int     addr_samesubnet (const sockaddr_u *, const sockaddr_u *,
        !           256:                                 const sockaddr_u *, const sockaddr_u *);
        !           257: static int     create_sockets  (u_short);
        !           258: static SOCKET  open_socket     (sockaddr_u *, int, int, endpt *);
        !           259: static char *  fdbits          (int, fd_set *);
        !           260: static void    set_reuseaddr   (int);
        !           261: static isc_boolean_t   socket_broadcast_enable  (struct interface *, SOCKET, sockaddr_u *);
        !           262: static isc_boolean_t   socket_broadcast_disable (struct interface *, sockaddr_u *);
        !           263: 
        !           264: typedef struct remaddr remaddr_t;
        !           265: 
        !           266: struct remaddr {
        !           267:        remaddr_t *             link;
        !           268:        sockaddr_u              addr;
        !           269:        endpt *                 ep;
        !           270: };
        !           271: 
        !           272: remaddr_t *    remoteaddr_list;
        !           273: endpt *                ep_list;        /* complete endpt list */
        !           274: endpt *                mc4_list;       /* IPv4 mcast-capable unicast endpts */
        !           275: endpt *                mc6_list;       /* IPv6 mcast-capable unicast endpts */
        !           276: 
        !           277: static endpt * wildipv4;
        !           278: static endpt * wildipv6;
        !           279: 
        !           280: static void    add_fd_to_list          (SOCKET, enum desc_type);
        !           281: static endpt * find_addr_in_list       (sockaddr_u *);
        !           282: static endpt * find_flagged_addr_in_list(sockaddr_u *, u_int32);
        !           283: static void    delete_addr_from_list   (sockaddr_u *);
        !           284: static void    delete_interface_from_list(endpt *);
        !           285: static void    close_and_delete_fd_from_list(SOCKET);
        !           286: static void    add_addr_to_list        (sockaddr_u *, endpt *);
        !           287: static void    create_wildcards        (u_short);
        !           288: static endpt * getinterface            (sockaddr_u *, u_int32);
        !           289: static endpt * findlocalinterface      (sockaddr_u *, int, int);
        !           290: static endpt * findclosestinterface    (sockaddr_u *, int);
        !           291: #ifdef DEBUG
        !           292: static const char *    action_text     (nic_rule_action);
        !           293: #endif
        !           294: static nic_rule_action interface_action(char *, sockaddr_u *, u_int32);
        !           295: static void            convert_isc_if  (isc_interface_t *,
        !           296:                                         endpt *, u_short);
        !           297: static void            calc_addr_distance(sockaddr_u *,
        !           298:                                           const sockaddr_u *,
        !           299:                                           const sockaddr_u *);
        !           300: static int             cmp_addr_distance(const sockaddr_u *,
        !           301:                                          const sockaddr_u *);
        !           302: 
        !           303: /*
        !           304:  * Routines to read the ntp packets
        !           305:  */
        !           306: #if !defined(HAVE_IO_COMPLETION_PORT)
        !           307: static inline int     read_network_packet      (SOCKET, struct interface *, l_fp);
        !           308: static inline int     read_refclock_packet     (SOCKET, struct refclockio *, l_fp);
        !           309: #endif
        !           310: 
        !           311: 
        !           312: #ifdef SYS_WINNT
        !           313: /*
        !           314:  * Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom
        !           315:  * to not work correctly, returning a WSACONNRESET error when a WSASendTo
        !           316:  * fails with an "ICMP port unreachable" response and preventing the
        !           317:  * socket from using the WSARecvFrom in subsequent operations.
        !           318:  * The function below fixes this, but requires that Windows 2000
        !           319:  * Service Pack 2 or later be installed on the system.  NT 4.0
        !           320:  * systems are not affected by this and work correctly.
        !           321:  * See Microsoft Knowledge Base Article Q263823 for details of this.
        !           322:  */
        !           323: void
        !           324: connection_reset_fix(
        !           325:        SOCKET          fd,
        !           326:        sockaddr_u *    addr
        !           327:        )
        !           328: {
        !           329:        DWORD dw;
        !           330:        BOOL  bNewBehavior = FALSE;
        !           331:        DWORD status;
        !           332: 
        !           333:        /*
        !           334:         * disable bad behavior using IOCTL: SIO_UDP_CONNRESET
        !           335:         * NT 4.0 has no problem
        !           336:         */
        !           337:        if (isc_win32os_majorversion() >= 5) {
        !           338:                status = WSAIoctl(fd, SIO_UDP_CONNRESET, &bNewBehavior,
        !           339:                                  sizeof(bNewBehavior), NULL, 0,
        !           340:                                  &dw, NULL, NULL);
        !           341:                if (SOCKET_ERROR == status)
        !           342:                        msyslog(LOG_ERR,
        !           343:                                "connection_reset_fix() failed for address %s: %m", 
        !           344:                                stoa(addr));
        !           345:        }
        !           346: }
        !           347: #endif
        !           348: 
        !           349: /*
        !           350:  * on Unix systems the stdio library typically
        !           351:  * makes use of file descriptors in the lower
        !           352:  * integer range.  stdio usually will make use
        !           353:  * of the file descriptors in the range of
        !           354:  * [0..FOPEN_MAX)
        !           355:  * in order to keep this range clean, for socket
        !           356:  * file descriptors we attempt to move them above
        !           357:  * FOPEN_MAX. This is not as easy as it sounds as
        !           358:  * FOPEN_MAX changes from implementation to implementation
        !           359:  * and may exceed to current file decriptor limits.
        !           360:  * We are using following strategy:
        !           361:  * - keep a current socket fd boundary initialized with
        !           362:  *   max(0, min(getdtablesize() - FD_CHUNK, FOPEN_MAX))
        !           363:  * - attempt to move the descriptor to the boundary or
        !           364:  *   above.
        !           365:  *   - if that fails and boundary > 0 set boundary
        !           366:  *     to min(0, socket_fd_boundary - FD_CHUNK)
        !           367:  *     -> retry
        !           368:  *     if failure and boundary == 0 return old fd
        !           369:  *   - on success close old fd return new fd
        !           370:  *
        !           371:  * effects:
        !           372:  *   - fds will be moved above the socket fd boundary
        !           373:  *     if at all possible.
        !           374:  *   - the socket boundary will be reduced until
        !           375:  *     allocation is possible or 0 is reached - at this
        !           376:  *     point the algrithm will be disabled
        !           377:  */
        !           378: static int
        !           379: move_fd(
        !           380:        SOCKET fd
        !           381:        )
        !           382: {
        !           383: #if !defined(SYS_WINNT) && defined(F_DUPFD)
        !           384: #ifndef FD_CHUNK
        !           385: #define FD_CHUNK       10
        !           386: #endif
        !           387: /*
        !           388:  * number of fds we would like to have for
        !           389:  * stdio FILE* available.
        !           390:  * we can pick a "low" number as our use of
        !           391:  * FILE* is limited to log files and temporarily
        !           392:  * to data and config files. Except for log files
        !           393:  * we don't keep the other FILE* open beyond the
        !           394:  * scope of the function that opened it.
        !           395:  */
        !           396: #ifndef FD_PREFERRED_SOCKBOUNDARY
        !           397: #define FD_PREFERRED_SOCKBOUNDARY 48
        !           398: #endif
        !           399: 
        !           400: #ifndef HAVE_GETDTABLESIZE
        !           401: /*
        !           402:  * if we have no idea about the max fd value set up things
        !           403:  * so we will start at FOPEN_MAX
        !           404:  */
        !           405: #define getdtablesize() (FOPEN_MAX+FD_CHUNK)
        !           406: #endif
        !           407: 
        !           408: #ifndef FOPEN_MAX
        !           409: #define FOPEN_MAX      20      /* assume that for the lack of anything better */
        !           410: #endif
        !           411:        static SOCKET socket_boundary = -1;
        !           412:        SOCKET newfd;
        !           413: 
        !           414:        NTP_REQUIRE((int)fd >= 0);
        !           415: 
        !           416:        /*
        !           417:         * check whether boundary has be set up
        !           418:         * already
        !           419:         */
        !           420:        if (socket_boundary == -1) {
        !           421:                socket_boundary = max(0, min(getdtablesize() - FD_CHUNK, 
        !           422:                                             min(FOPEN_MAX, FD_PREFERRED_SOCKBOUNDARY)));
        !           423: #ifdef DEBUG
        !           424:                msyslog(LOG_DEBUG,
        !           425:                        "ntp_io: estimated max descriptors: %d, initial socket boundary: %d",
        !           426:                        getdtablesize(), socket_boundary);
        !           427: #endif
        !           428:        }
        !           429: 
        !           430:        /*
        !           431:         * Leave a space for stdio to work in. potentially moving the
        !           432:         * socket_boundary lower until allocation succeeds.
        !           433:         */
        !           434:        do {
        !           435:                if (fd >= 0 && fd < socket_boundary) {
        !           436:                        /* inside reserved range: attempt to move fd */
        !           437:                        newfd = fcntl(fd, F_DUPFD, socket_boundary);
        !           438:                        
        !           439:                        if (newfd != -1) {
        !           440:                                /* success: drop the old one - return the new one */
        !           441:                                close(fd);
        !           442:                                return newfd;
        !           443:                        }
        !           444:                } else {
        !           445:                        /* outside reserved range: no work - return the original one */
        !           446:                        return fd;
        !           447:                }
        !           448:                socket_boundary = max(0, socket_boundary - FD_CHUNK);
        !           449: #ifdef DEBUG
        !           450:                msyslog(LOG_DEBUG,
        !           451:                        "ntp_io: selecting new socket boundary: %d",
        !           452:                        socket_boundary);
        !           453: #endif
        !           454:        } while (socket_boundary > 0);
        !           455: #else
        !           456:        NTP_REQUIRE((int)fd >= 0);
        !           457: #endif /* !defined(SYS_WINNT) && defined(F_DUPFD) */
        !           458:        return fd;
        !           459: }
        !           460: 
        !           461: #ifdef DEBUG_TIMING
        !           462: /*
        !           463:  * collect timing information for various processing
        !           464:  * paths. currently we only pass then on to the file
        !           465:  * for later processing. this could also do histogram
        !           466:  * based analysis in other to reduce the load (and skew)
        !           467:  * dur to the file output
        !           468:  */
        !           469: void
        !           470: collect_timing(struct recvbuf *rb, const char *tag, int count, l_fp *dts)
        !           471: {
        !           472:        char buf[256];
        !           473: 
        !           474:        snprintf(buf, sizeof(buf), "%s %d %s %s", 
        !           475:                 (rb != NULL)
        !           476:                     ? ((rb->dstadr != NULL)
        !           477:                            ? stoa(&rb->recv_srcadr)
        !           478:                            : "-REFCLOCK-")
        !           479:                     : "-",
        !           480:                 count, lfptoa(dts, 9), tag);
        !           481:        record_timing_stats(buf);
        !           482: }
        !           483: #endif
        !           484: 
        !           485: /*
        !           486:  * About dynamic interfaces, sockets, reception and more...
        !           487:  *
        !           488:  * the code solves following tasks:
        !           489:  *
        !           490:  *   - keep a current list of active interfaces in order
        !           491:  *     to bind to to the interface address on NTP_PORT so that
        !           492:  *     all wild and specific bindings for NTP_PORT are taken by ntpd
        !           493:  *     to avoid other daemons messing with the time or sockets.
        !           494:  *   - all interfaces keep a list of peers that are referencing 
        !           495:  *     the interface in order to quickly re-assign the peers to
        !           496:  *     new interface in case an interface is deleted (=> gone from system or
        !           497:  *     down)
        !           498:  *   - have a preconfigured socket ready with the right local address
        !           499:  *     for transmission and reception
        !           500:  *   - have an address list for all destination addresses used within ntpd
        !           501:  *     to find the "right" preconfigured socket.
        !           502:  *   - facilitate updating the internal interface list with respect to
        !           503:  *     the current kernel state
        !           504:  *
        !           505:  * special issues:
        !           506:  *
        !           507:  *   - mapping of multicast addresses to the interface affected is not always
        !           508:  *     one to one - especially on hosts with multiple interfaces
        !           509:  *     the code here currently allocates a separate interface entry for those
        !           510:  *     multicast addresses
        !           511:  *     iff it is able to bind to a *new* socket with the multicast address (flags |= MCASTIF)
        !           512:  *     in case of failure the multicast address is bound to an existing interface.
        !           513:  *   - on some systems it is perfectly legal to assign the same address to
        !           514:  *     multiple interfaces. Therefore this code does not keep a list of interfaces
        !           515:  *     but a list of interfaces that represent a unique address as determined by the kernel
        !           516:  *     by the procedure in findlocalinterface. Thus it is perfectly legal to see only
        !           517:  *     one representative of a group of real interfaces if they share the same address.
        !           518:  * 
        !           519:  * Frank Kardel 20050910
        !           520:  */
        !           521: 
        !           522: /*
        !           523:  * init_io - initialize I/O data structures and call socket creation routine
        !           524:  */
        !           525: void
        !           526: init_io(void)
        !           527: {
        !           528:        /*
        !           529:         * Init buffer free list and stat counters
        !           530:         */
        !           531:        init_recvbuff(RECV_INIT);
        !           532: 
        !           533: #ifdef SYS_WINNT
        !           534:        init_io_completion_port();
        !           535: #endif /* SYS_WINNT */
        !           536: 
        !           537: #if defined(HAVE_SIGNALED_IO)
        !           538:        (void) set_signal();
        !           539: #endif
        !           540: }
        !           541: 
        !           542: 
        !           543: /*
        !           544:  * io_open_sockets - call socket creation routine
        !           545:  */
        !           546: void
        !           547: io_open_sockets(void)
        !           548: {
        !           549:        static int already_opened;
        !           550: 
        !           551:        if (already_opened || HAVE_OPT( SAVECONFIGQUIT ))
        !           552:                return;
        !           553: 
        !           554:        already_opened = 1;
        !           555: 
        !           556:        /*
        !           557:         * Create the sockets
        !           558:         */
        !           559:        BLOCKIO();
        !           560:        create_sockets(NTP_PORT);
        !           561:        UNBLOCKIO();
        !           562: 
        !           563:        init_async_notifications();
        !           564: 
        !           565:        DPRINTF(3, ("io_open_sockets: maxactivefd %d\n", maxactivefd));
        !           566: }
        !           567: 
        !           568: 
        !           569: #ifdef DEBUG
        !           570: /*
        !           571:  * function to dump the contents of the interface structure
        !           572:  * for debugging use only.
        !           573:  */
        !           574: void
        !           575: interface_dump(const endpt *itf)
        !           576: {
        !           577:        printf("Dumping interface: %p\n", itf);
        !           578:        printf("fd = %d\n", itf->fd);
        !           579:        printf("bfd = %d\n", itf->bfd);
        !           580:        printf("sin = %s,\n", stoa(&itf->sin));
        !           581:        sockaddr_dump(&itf->sin);
        !           582:        printf("bcast = %s,\n", stoa(&itf->bcast));
        !           583:        sockaddr_dump(&itf->bcast);
        !           584:        printf("mask = %s,\n", stoa(&itf->mask));
        !           585:        sockaddr_dump(&itf->mask);
        !           586:        printf("name = %s\n", itf->name);
        !           587:        printf("flags = 0x%08x\n", itf->flags);
        !           588:        printf("last_ttl = %d\n", itf->last_ttl);
        !           589:        printf("addr_refid = %08x\n", itf->addr_refid);
        !           590:        printf("num_mcast = %d\n", itf->num_mcast);
        !           591:        printf("received = %ld\n", itf->received);
        !           592:        printf("sent = %ld\n", itf->sent);
        !           593:        printf("notsent = %ld\n", itf->notsent);
        !           594:        printf("ifindex = %u\n", itf->ifindex);
        !           595:        printf("peercnt = %u\n", itf->peercnt);
        !           596:        printf("phase = %u\n", itf->phase);
        !           597: }
        !           598: 
        !           599: /*
        !           600:  * sockaddr_dump - hex dump the start of a sockaddr_u
        !           601:  */
        !           602: static void
        !           603: sockaddr_dump(const sockaddr_u *psau)
        !           604: {
        !           605:        /* Limit the size of the sockaddr_storage hex dump */
        !           606:        const int maxsize = min(32, sizeof(psau->sa6));
        !           607:        const u_char *  cp;
        !           608:        int             i;
        !           609: 
        !           610:        cp = (const void *)&psau->sa;
        !           611: 
        !           612:        for(i = 0; i < maxsize; i++) {
        !           613:                printf("%02x", *cp++);
        !           614:                if (!((i + 1) % 4))
        !           615:                        printf(" ");
        !           616:        }
        !           617:        printf("\n");
        !           618: }
        !           619: 
        !           620: /*
        !           621:  * print_interface - helper to output debug information
        !           622:  */
        !           623: static void
        !           624: print_interface(const endpt *iface, char *pfx, char *sfx)
        !           625: {
        !           626:        printf("%sinterface #%d: fd=%d, bfd=%d, name=%s, flags=0x%x, ifindex=%u, sin=%s",
        !           627:               pfx,
        !           628:               iface->ifnum,
        !           629:               iface->fd,
        !           630:               iface->bfd,
        !           631:               iface->name,
        !           632:               iface->flags,
        !           633:               iface->ifindex,
        !           634:               stoa(&iface->sin));
        !           635:        if (AF_INET == iface->family) {
        !           636:                if (iface->flags & INT_BROADCAST)
        !           637:                        printf(", bcast=%s", stoa(&iface->bcast));
        !           638:                printf(", mask=%s", stoa(&iface->mask));
        !           639:        }
        !           640:        printf(", %s:%s",
        !           641:               (iface->ignore_packets) 
        !           642:                   ? "Disabled"
        !           643:                   : "Enabled",
        !           644:               sfx);
        !           645:        if (debug > 4)  /* in-depth debugging only */
        !           646:                interface_dump(iface);
        !           647: }
        !           648: #endif
        !           649: 
        !           650: #if !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET)
        !           651: /*
        !           652:  * create an asyncio_reader structure
        !           653:  */
        !           654: static struct asyncio_reader *
        !           655: new_asyncio_reader(void)
        !           656: {
        !           657:        struct asyncio_reader *reader;
        !           658: 
        !           659:        reader = emalloc(sizeof(*reader));
        !           660: 
        !           661:        memset(reader, 0, sizeof(*reader));
        !           662:        reader->fd = INVALID_SOCKET;
        !           663:        return reader;
        !           664: }
        !           665: 
        !           666: /*
        !           667:  * delete a reader
        !           668:  */
        !           669: static void
        !           670: delete_asyncio_reader(
        !           671:        struct asyncio_reader *reader
        !           672:        )
        !           673: {
        !           674:        free(reader);
        !           675: }
        !           676: 
        !           677: /*
        !           678:  * add asynchio_reader
        !           679:  */
        !           680: static void
        !           681: add_asyncio_reader(
        !           682:        struct asyncio_reader * reader, 
        !           683:        enum desc_type          type)
        !           684: {
        !           685:        LINK_SLIST(asyncio_reader_list, reader, link);
        !           686:        add_fd_to_list(reader->fd, type);
        !           687: }
        !           688:        
        !           689: /*
        !           690:  * remove asynchio_reader
        !           691:  */
        !           692: static void
        !           693: remove_asyncio_reader(
        !           694:        struct asyncio_reader *reader
        !           695:        )
        !           696: {
        !           697:        struct asyncio_reader *unlinked;
        !           698: 
        !           699:        UNLINK_SLIST(unlinked, asyncio_reader_list, reader, link,
        !           700:            struct asyncio_reader);
        !           701: 
        !           702:        if (reader->fd != INVALID_SOCKET)
        !           703:                close_and_delete_fd_from_list(reader->fd);
        !           704: 
        !           705:        reader->fd = INVALID_SOCKET;
        !           706: }
        !           707: #endif /* !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) */
        !           708: 
        !           709: 
        !           710: /* compare two sockaddr prefixes */
        !           711: static int
        !           712: addr_eqprefix(
        !           713:        const sockaddr_u *      a,
        !           714:        const sockaddr_u *      b,
        !           715:        int                     prefixlen
        !           716:        )
        !           717: {
        !           718:        isc_netaddr_t           isc_a;
        !           719:        isc_netaddr_t           isc_b;
        !           720:        isc_sockaddr_t          isc_sa;
        !           721: 
        !           722:        memset(&isc_sa, 0, sizeof(isc_sa));
        !           723:        memcpy(&isc_sa.type.sa, &a->sa, 
        !           724:               min(sizeof(isc_sa.type), sizeof(*a)));
        !           725:        isc_netaddr_fromsockaddr(&isc_a, &isc_sa);
        !           726: 
        !           727:        memset(&isc_sa, 0, sizeof(isc_sa));
        !           728:        memcpy(&isc_sa.type.sa, &b->sa, 
        !           729:               min(sizeof(isc_sa.type), sizeof(*b)));
        !           730:        isc_netaddr_fromsockaddr(&isc_b, &isc_sa);
        !           731: 
        !           732:        return (int)isc_netaddr_eqprefix(&isc_a, &isc_b,
        !           733:                                         (u_int)prefixlen);
        !           734: }
        !           735: 
        !           736: 
        !           737: static int
        !           738: addr_samesubnet(
        !           739:        const sockaddr_u *      a,
        !           740:        const sockaddr_u *      a_mask,
        !           741:        const sockaddr_u *      b,
        !           742:        const sockaddr_u *      b_mask
        !           743:        )
        !           744: {
        !           745:        const u_int32 * pa;
        !           746:        const u_int32 * pa_limit;
        !           747:        const u_int32 * pb;
        !           748:        const u_int32 * pm;
        !           749:        size_t          loops;
        !           750: 
        !           751:        NTP_REQUIRE(AF(a) == AF(a_mask));
        !           752:        NTP_REQUIRE(AF(b) == AF(b_mask));
        !           753:        /*
        !           754:         * With address and mask families verified to match, comparing
        !           755:         * the masks also validates the address's families match.
        !           756:         */
        !           757:        if (!SOCK_EQ(a_mask, b_mask))
        !           758:                return FALSE;
        !           759: 
        !           760:        if (IS_IPV6(a)) {
        !           761:                loops = sizeof(NSRCADR6(a)) / sizeof(*pa);
        !           762:                pa = (const void *)&NSRCADR6(a);
        !           763:                pb = (const void *)&NSRCADR6(b);
        !           764:                pm = (const void *)&NSRCADR6(a_mask);
        !           765:        } else {
        !           766:                loops = sizeof(NSRCADR(a)) / sizeof(*pa);
        !           767:                pa = (const void *)&NSRCADR(a);
        !           768:                pb = (const void *)&NSRCADR(b);
        !           769:                pm = (const void *)&NSRCADR(a_mask);
        !           770:        }
        !           771:        for (pa_limit = pa + loops; pa < pa_limit; pa++, pb++, pm++)
        !           772:                if ((*pa & *pm) != (*pb & *pm))
        !           773:                        return FALSE;
        !           774: 
        !           775:        return TRUE;
        !           776: }
        !           777: 
        !           778: 
        !           779: /*
        !           780:  * Code to tell if we have an IP address
        !           781:  * If we have then return the sockaddr structure
        !           782:  * and set the return value
        !           783:  * see the bind9/getaddresses.c for details
        !           784:  */
        !           785: int
        !           786: is_ip_address(
        !           787:        const char *    host,
        !           788:        sockaddr_u *    addr
        !           789:        )
        !           790: {
        !           791:        struct in_addr in4;
        !           792:        struct in6_addr in6;
        !           793:        char tmpbuf[128];
        !           794:        char *pch;
        !           795: 
        !           796:        NTP_REQUIRE(host != NULL);
        !           797:        NTP_REQUIRE(addr != NULL);
        !           798: 
        !           799:        memset(addr, 0, sizeof(*addr));
        !           800: 
        !           801:        /*
        !           802:         * Try IPv4, then IPv6.  In order to handle the extended format
        !           803:         * for IPv6 scoped addresses (address%scope_ID), we'll use a local
        !           804:         * working buffer of 128 bytes.  The length is an ad-hoc value, but
        !           805:         * should be enough for this purpose; the buffer can contain a string
        !           806:         * of at least 80 bytes for scope_ID in addition to any IPv6 numeric
        !           807:         * addresses (up to 46 bytes), the delimiter character and the
        !           808:         * terminating NULL character.
        !           809:         */
        !           810:        if (inet_pton(AF_INET, host, &in4) == 1) {
        !           811:                AF(addr) = AF_INET;
        !           812:                SET_ADDR4N(addr, in4.s_addr);
        !           813: 
        !           814:                return TRUE;
        !           815:        } else if (sizeof(tmpbuf) > strlen(host)) {
        !           816:                if ('[' == host[0]) {
        !           817:                        strncpy(tmpbuf, &host[1], sizeof(tmpbuf));
        !           818:                        pch = strchr(tmpbuf, ']');
        !           819:                        if (pch != NULL)
        !           820:                                *pch = '\0';
        !           821:                } else
        !           822:                        strncpy(tmpbuf, host, sizeof(tmpbuf));
        !           823:                pch = strchr(tmpbuf, '%');
        !           824:                if (pch != NULL)
        !           825:                        *pch = '\0';
        !           826: 
        !           827:                if (inet_pton(AF_INET6, tmpbuf, &in6) == 1) {
        !           828:                        AF(addr) = AF_INET6;
        !           829:                        SET_ADDR6N(addr, in6);
        !           830: 
        !           831:                        return TRUE;
        !           832:                }
        !           833:        }
        !           834:        /*
        !           835:         * If we got here it was not an IP address
        !           836:         */
        !           837:        return FALSE;
        !           838: }
        !           839: 
        !           840: 
        !           841: /*
        !           842:  * interface list enumerator - visitor pattern
        !           843:  */
        !           844: void
        !           845: interface_enumerate(
        !           846:        interface_receiver_t    receiver, 
        !           847:        void *                  data
        !           848:        )
        !           849: {
        !           850:        interface_info_t ifi;
        !           851: 
        !           852:        ifi.action = IFS_EXISTS;
        !           853:        for (ifi.ep = ep_list; ifi.ep != NULL; ifi.ep = ifi.ep->elink)
        !           854:                (*receiver)(data, &ifi);
        !           855: }
        !           856: 
        !           857: /*
        !           858:  * do standard initialization of interface structure
        !           859:  */
        !           860: static void
        !           861: init_interface(
        !           862:        endpt *ep
        !           863:        )
        !           864: {
        !           865:        memset(ep, 0, sizeof(*ep));
        !           866:        ep->fd = INVALID_SOCKET;
        !           867:        ep->bfd = INVALID_SOCKET;
        !           868:        ep->phase = sys_interphase;
        !           869: }
        !           870: 
        !           871: 
        !           872: /*
        !           873:  * create new interface structure initialize from
        !           874:  * template structure or via standard initialization
        !           875:  * function
        !           876:  */
        !           877: static struct interface *
        !           878: new_interface(
        !           879:        struct interface *interface
        !           880:        )
        !           881: {
        !           882:        static u_int            sys_ifnum = 0;
        !           883:        struct interface *      iface;
        !           884: 
        !           885:        iface = emalloc(sizeof(*iface));
        !           886: 
        !           887:        if (NULL == interface)
        !           888:                init_interface(iface);
        !           889:        else                            /* use the template */
        !           890:                memcpy(iface, interface, sizeof(*iface));
        !           891: 
        !           892:        /* count every new instance of an interface in the system */
        !           893:        iface->ifnum = sys_ifnum++;
        !           894:        iface->starttime = current_time;
        !           895: 
        !           896:        return iface;
        !           897: }
        !           898: 
        !           899: 
        !           900: /*
        !           901:  * return interface storage into free memory pool
        !           902:  */
        !           903: static inline void
        !           904: delete_interface(
        !           905:        endpt *ep
        !           906:        )
        !           907: {
        !           908:        free(ep);
        !           909: }
        !           910: 
        !           911: 
        !           912: /*
        !           913:  * link interface into list of known interfaces
        !           914:  */
        !           915: static void
        !           916: add_interface(
        !           917:        endpt * ep
        !           918:        )
        !           919: {
        !           920:        endpt **        pmclisthead;
        !           921:        endpt *         scan;
        !           922:        endpt *         scan_next;
        !           923:        endpt *         unlinked;
        !           924:        sockaddr_u *    addr;
        !           925:        int             ep_local;
        !           926:        int             scan_local;
        !           927:        int             same_subnet;
        !           928:        int             ep_univ_iid;    /* iface ID from MAC address */
        !           929:        int             scan_univ_iid;  /* see RFC 4291 */
        !           930:        int             ep_privacy;     /* random local iface ID */
        !           931:        int             scan_privacy;   /* see RFC 4941 */
        !           932:        int             rc;
        !           933: 
        !           934:        /*
        !           935:         * Calculate the address hash
        !           936:         */
        !           937:        ep->addr_refid = addr2refid(&ep->sin);
        !           938: 
        !           939:        LINK_SLIST(ep_list, ep, elink);
        !           940:        ninterfaces++;
        !           941: #ifdef MCAST
        !           942:        /* the rest is for enabled multicast-capable addresses only */
        !           943:        if (ep->ignore_packets || !(INT_MULTICAST & ep->flags) ||
        !           944:            INT_LOOPBACK & ep->flags)
        !           945:                return;
        !           946: # ifndef INCLUDE_IPV6_MULTICAST_SUPPORT
        !           947:        if (AF_INET6 == ep->family)
        !           948:                return;
        !           949: # endif
        !           950:        pmclisthead = (AF_INET == ep->family)
        !           951:                         ? &mc4_list
        !           952:                         : &mc6_list;
        !           953: 
        !           954:        if (AF_INET6 == ep->family) {
        !           955:                ep_local =
        !           956:                    IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(&ep->sin)) ||
        !           957:                    IN6_IS_ADDR_SITELOCAL(PSOCK_ADDR6(&ep->sin));
        !           958:                ep_univ_iid = IS_IID_UNIV(&ep->sin);
        !           959:                ep_privacy = !!(INT_PRIVACY & ep->flags);
        !           960:        } else {
        !           961:                ep_local = FALSE;
        !           962:                ep_univ_iid = FALSE;
        !           963:                ep_privacy = FALSE;
        !           964:        }
        !           965:        DPRINTF(4, ("add_interface mcast-capable %s%s%s%s\n",
        !           966:                    stoa(&ep->sin),
        !           967:                    (ep_local) ? " link/scope-local" : "",
        !           968:                    (ep_univ_iid) ? " univ-IID" : "",
        !           969:                    (ep_privacy) ? " privacy" : ""));
        !           970:        /*
        !           971:         * If we have multiple local addresses on the same network
        !           972:         * interface, and some are link- or site-local, do not multicast
        !           973:         * out from the link-/site-local addresses by default, to avoid
        !           974:         * duplicate manycastclient associations between v6 peers using
        !           975:         * link-local and global addresses.  link-local can still be
        !           976:         * chosen using "nic ignore myv6globalprefix::/64".
        !           977:         * Similarly, if we have multiple global addresses from the same
        !           978:         * prefix on the same network interface, multicast from one,
        !           979:         * preferring EUI-64, then static, then least RFC 4941 privacy
        !           980:         * addresses.
        !           981:         */
        !           982:        for (scan = *pmclisthead; scan != NULL; scan = scan_next) {
        !           983:                scan_next = scan->mclink;
        !           984:                if (ep->family != scan->family)
        !           985:                        continue;
        !           986:                if (strcmp(ep->name, scan->name))
        !           987:                        continue;
        !           988:                same_subnet = addr_samesubnet(&ep->sin, &ep->mask,
        !           989:                                              &scan->sin, &scan->mask);
        !           990:                if (AF_INET6 == ep->family) {
        !           991:                        addr = &scan->sin;
        !           992:                        scan_local =
        !           993:                            IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(addr)) ||
        !           994:                            IN6_IS_ADDR_SITELOCAL(PSOCK_ADDR6(addr));
        !           995:                        scan_univ_iid = IS_IID_UNIV(addr);
        !           996:                        scan_privacy = !!(INT_PRIVACY & scan->flags);
        !           997:                } else {
        !           998:                        scan_local = FALSE;
        !           999:                        scan_univ_iid = FALSE;
        !          1000:                        scan_privacy = FALSE;
        !          1001:                }
        !          1002:                DPRINTF(4, ("add_interface mcast-capable scan %s%s%s%s\n",
        !          1003:                            stoa(&scan->sin),
        !          1004:                            (scan_local) ? " link/scope-local" : "",
        !          1005:                            (scan_univ_iid) ? " univ-IID" : "",
        !          1006:                            (scan_privacy) ? " privacy" : ""));
        !          1007:                if ((ep_local && !scan_local) || (same_subnet && 
        !          1008:                    ((ep_privacy && !scan_privacy) ||
        !          1009:                     (!ep_univ_iid && scan_univ_iid)))) {
        !          1010:                        DPRINTF(4, ("did not add %s to %s of IPv6 multicast-capable list which already has %s\n",
        !          1011:                                stoa(&ep->sin),
        !          1012:                                (ep_local)
        !          1013:                                    ? "tail"
        !          1014:                                    : "head",
        !          1015:                                stoa(&scan->sin)));
        !          1016:                        return;
        !          1017:                }
        !          1018:                if ((scan_local && !ep_local) || (same_subnet &&
        !          1019:                    ((scan_privacy && !ep_privacy) ||
        !          1020:                     (!scan_univ_iid && ep_univ_iid)))) {
        !          1021:                        UNLINK_SLIST(unlinked, *pmclisthead,
        !          1022:                                     scan, mclink, endpt);
        !          1023:                        DPRINTF(4, ("%s %s from IPv6 multicast-capable list to add %s\n",
        !          1024:                                (unlinked != scan)
        !          1025:                                    ? "Failed to remove"
        !          1026:                                    : "removed",
        !          1027:                                stoa(&scan->sin), stoa(&ep->sin)));
        !          1028:                }
        !          1029:        }
        !          1030:        /*
        !          1031:         * Add link/site local at the tail of the multicast-
        !          1032:         * capable unicast interfaces list, so that ntpd will
        !          1033:         * send from global addresses before link-/site-local
        !          1034:         * ones.
        !          1035:         */
        !          1036:        if (ep_local)
        !          1037:                LINK_TAIL_SLIST(*pmclisthead, ep, mclink, endpt);
        !          1038:        else
        !          1039:                LINK_SLIST(*pmclisthead, ep, mclink);
        !          1040:        DPRINTF(4, ("added %s to %s of IPv%s multicast-capable unicast local address list\n",
        !          1041:                stoa(&ep->sin),
        !          1042:                (ep_local)
        !          1043:                    ? "tail"
        !          1044:                    : "head",
        !          1045:                (AF_INET == ep->family)
        !          1046:                    ? "4"
        !          1047:                    : "6"));
        !          1048: 
        !          1049:        /*
        !          1050:         * select the local address from which to send to multicast.
        !          1051:         */
        !          1052:        switch (AF(&ep->sin)) {
        !          1053:        case AF_INET :
        !          1054:                rc = setsockopt(ep->fd, IPPROTO_IP,
        !          1055:                                IP_MULTICAST_IF,
        !          1056:                                (void *)&NSRCADR(&ep->sin),
        !          1057:                                sizeof(NSRCADR(&ep->sin)));
        !          1058:                if (rc)
        !          1059:                        msyslog(LOG_ERR,
        !          1060:                                "setsockopt IP_MULTICAST_IF %s fails: %m",
        !          1061:                                stoa(&ep->sin));
        !          1062:                break;
        !          1063: # ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
        !          1064:        case AF_INET6 :
        !          1065:                rc = setsockopt(ep->fd, IPPROTO_IPV6,
        !          1066:                                 IPV6_MULTICAST_IF,
        !          1067:                                 (void *)&ep->ifindex,
        !          1068:                                 sizeof(ep->ifindex));
        !          1069:                if (rc)
        !          1070:                        msyslog(LOG_ERR,
        !          1071:                                "setsockopt IPV6_MULTICAST_IF %u for %s fails: %m",
        !          1072:                                ep->ifindex, stoa(&ep->sin));
        !          1073:                break;
        !          1074: # endif
        !          1075:        }
        !          1076: #endif /* MCAST */
        !          1077: }
        !          1078: 
        !          1079: 
        !          1080: /*
        !          1081:  * remove interface from known interface list and clean up
        !          1082:  * associated resources
        !          1083:  */
        !          1084: static void
        !          1085: remove_interface(
        !          1086:        endpt * ep
        !          1087:        )
        !          1088: {
        !          1089:        endpt *         unlinked;
        !          1090:        endpt **        pmclisthead;
        !          1091:        sockaddr_u      resmask;
        !          1092: 
        !          1093:        UNLINK_SLIST(unlinked, ep_list, ep, elink, endpt);
        !          1094:        if (!ep->ignore_packets && INT_MULTICAST & ep->flags) {
        !          1095:                pmclisthead = (AF_INET == ep->family)
        !          1096:                                 ? &mc4_list
        !          1097:                                 : &mc6_list;
        !          1098:                UNLINK_SLIST(unlinked, *pmclisthead, ep, mclink, endpt);
        !          1099:                DPRINTF(4, ("%s %s IPv%s multicast-capable unicast local address list\n",
        !          1100:                        stoa(&ep->sin),
        !          1101:                        (unlinked != NULL)
        !          1102:                            ? "removed from"
        !          1103:                            : "not found on",
        !          1104:                        (AF_INET == ep->family)
        !          1105:                            ? "4"
        !          1106:                            : "6"));
        !          1107:        }
        !          1108:        delete_interface_from_list(ep);
        !          1109:   
        !          1110:        if (ep->fd != INVALID_SOCKET) {
        !          1111:                msyslog(LOG_INFO,
        !          1112:                        "Deleting interface #%d %s, %s#%d, interface stats: received=%ld, sent=%ld, dropped=%ld, active_time=%ld secs",
        !          1113:                        ep->ifnum,
        !          1114:                        ep->name,
        !          1115:                        stoa(&ep->sin),
        !          1116:                        SRCPORT(&ep->sin),
        !          1117:                        ep->received,
        !          1118:                        ep->sent,
        !          1119:                        ep->notsent,
        !          1120:                        current_time - ep->starttime);
        !          1121:                close_and_delete_fd_from_list(ep->fd);
        !          1122:        }
        !          1123: 
        !          1124:        if (ep->bfd != INVALID_SOCKET) {
        !          1125:                msyslog(LOG_INFO,
        !          1126:                        "Deleting broadcast address %s#%d from interface #%d %s",
        !          1127:                        stoa(&ep->bcast), SRCPORT(&ep->bcast),
        !          1128:                        ep->ifnum, ep->name);
        !          1129:                close_and_delete_fd_from_list(ep->bfd);
        !          1130:        }
        !          1131: 
        !          1132:        ninterfaces--;
        !          1133:        ntp_monclearinterface(ep);
        !          1134: 
        !          1135:        /* remove restrict interface entry */
        !          1136:        SET_HOSTMASK(&resmask, AF(&ep->sin));
        !          1137:        hack_restrict(RESTRICT_REMOVEIF, &ep->sin, &resmask,
        !          1138:                      RESM_NTPONLY | RESM_INTERFACE, RES_IGNORE);
        !          1139: }
        !          1140: 
        !          1141: 
        !          1142: static void
        !          1143: log_listen_address(
        !          1144:        endpt * ep
        !          1145:        )
        !          1146: {
        !          1147:        msyslog(LOG_INFO, "%s on %d %s %s UDP %d",
        !          1148:                (ep->ignore_packets) 
        !          1149:                    ? "Listen and drop"
        !          1150:                    : "Listen normally",
        !          1151:                ep->ifnum,
        !          1152:                ep->name,
        !          1153:                stoa(&ep->sin),
        !          1154:                SRCPORT(&ep->sin));
        !          1155: }
        !          1156: 
        !          1157: 
        !          1158: static void
        !          1159: create_wildcards(
        !          1160:        u_short port
        !          1161:        )
        !          1162: {
        !          1163:        int                     v4wild, v6wild;
        !          1164:        sockaddr_u              wildaddr;
        !          1165:        nic_rule_action         action;
        !          1166:        struct interface *      wildif;
        !          1167: 
        !          1168:        /*
        !          1169:         * silence "potentially uninitialized" warnings from VC9
        !          1170:         * failing to follow the logic.  Ideally action could remain
        !          1171:         * uninitialized, and the memset be the first statement under
        !          1172:         * the first if (v4wild).
        !          1173:         */
        !          1174:        action = ACTION_LISTEN;
        !          1175:        memset(&wildaddr, 0, sizeof(wildaddr));
        !          1176:        
        !          1177:        /*
        !          1178:         * create pseudo-interface with wildcard IPv4 address
        !          1179:         */
        !          1180:        v4wild = ipv4_works;
        !          1181:        if (v4wild) {
        !          1182:                /* set wildaddr to the v4 wildcard address 0.0.0.0 */
        !          1183:                AF(&wildaddr) = AF_INET;
        !          1184:                SET_ADDR4(&wildaddr, INADDR_ANY);
        !          1185:                SET_PORT(&wildaddr, port);
        !          1186: 
        !          1187:                /* check for interface/nic rules affecting the wildcard */
        !          1188:                action = interface_action(NULL, &wildaddr, 0);
        !          1189:                v4wild = (ACTION_IGNORE != action);
        !          1190:        }
        !          1191:        if (v4wild) {
        !          1192:                wildif = new_interface(NULL);
        !          1193: 
        !          1194:                strncpy(wildif->name, "v4wildcard", sizeof(wildif->name));
        !          1195:                memcpy(&wildif->sin, &wildaddr, sizeof(wildif->sin));
        !          1196:                wildif->family = AF_INET;
        !          1197:                AF(&wildif->mask) = AF_INET;
        !          1198:                SET_ONESMASK(&wildif->mask);
        !          1199: 
        !          1200:                wildif->flags = INT_BROADCAST | INT_UP | INT_WILDCARD;
        !          1201:                wildif->ignore_packets = (ACTION_DROP == action);
        !          1202: #if defined(MCAST)
        !          1203:                /*
        !          1204:                 * enable multicast reception on the broadcast socket
        !          1205:                 */
        !          1206:                AF(&wildif->bcast) = AF_INET;
        !          1207:                SET_ADDR4(&wildif->bcast, INADDR_ANY);
        !          1208:                SET_PORT(&wildif->bcast, port);
        !          1209: #endif /* MCAST */
        !          1210:                wildif->fd = open_socket(&wildif->sin, 0, 1, wildif);
        !          1211: 
        !          1212:                if (wildif->fd != INVALID_SOCKET) {
        !          1213:                        wildipv4 = wildif;
        !          1214:                        any_interface = wildif;
        !          1215:                        
        !          1216:                        add_addr_to_list(&wildif->sin, wildif);
        !          1217:                        add_interface(wildif);
        !          1218:                        log_listen_address(wildif);
        !          1219:                } else {
        !          1220:                        msyslog(LOG_ERR, 
        !          1221:                                "unable to bind to wildcard address %s - another process may be running - EXITING",
        !          1222:                                stoa(&wildif->sin));
        !          1223:                        exit(1);
        !          1224:                }
        !          1225:                DPRINT_INTERFACE(2, (wildif, "created ", "\n"));
        !          1226:        }
        !          1227: 
        !          1228: #ifdef INCLUDE_IPV6_SUPPORT
        !          1229:        /*
        !          1230:         * create pseudo-interface with wildcard IPv6 address
        !          1231:         */
        !          1232:        v6wild = ipv6_works;
        !          1233:        if (v6wild) {
        !          1234:                /* set wildaddr to the v6 wildcard address :: */
        !          1235:                memset(&wildaddr, 0, sizeof(wildaddr));
        !          1236:                AF(&wildaddr) = AF_INET6;
        !          1237:                SET_ADDR6N(&wildaddr, in6addr_any);
        !          1238:                SET_PORT(&wildaddr, port);
        !          1239:                SET_SCOPE(&wildaddr, 0);
        !          1240: 
        !          1241:                /* check for interface/nic rules affecting the wildcard */
        !          1242:                action = interface_action(NULL, &wildaddr, 0);
        !          1243:                v6wild = (ACTION_IGNORE != action);
        !          1244:        }
        !          1245:        if (v6wild) {
        !          1246:                wildif = new_interface(NULL);
        !          1247: 
        !          1248:                strncpy(wildif->name, "v6wildcard", sizeof(wildif->name));
        !          1249:                memcpy(&wildif->sin, &wildaddr, sizeof(wildif->sin));
        !          1250:                wildif->family = AF_INET6;
        !          1251:                AF(&wildif->mask) = AF_INET6;
        !          1252:                SET_ONESMASK(&wildif->mask);
        !          1253: 
        !          1254:                wildif->flags = INT_UP | INT_WILDCARD;
        !          1255:                wildif->ignore_packets = (ACTION_DROP == action);
        !          1256: 
        !          1257:                wildif->fd = open_socket(&wildif->sin, 0, 1, wildif);
        !          1258: 
        !          1259:                if (wildif->fd != INVALID_SOCKET) {
        !          1260:                        wildipv6 = wildif;
        !          1261:                        any6_interface = wildif;
        !          1262:                        add_addr_to_list(&wildif->sin, wildif);
        !          1263:                        add_interface(wildif);
        !          1264:                        log_listen_address(wildif);
        !          1265:                } else {
        !          1266:                        msyslog(LOG_ERR,
        !          1267:                                "unable to bind to wildcard address %s - another process may be running - EXITING",
        !          1268:                                stoa(&wildif->sin));
        !          1269:                        exit(1);
        !          1270:                }
        !          1271:                DPRINT_INTERFACE(2, (wildif, "created ", "\n"));
        !          1272:        }
        !          1273: #endif
        !          1274: }
        !          1275: 
        !          1276: 
        !          1277: /*
        !          1278:  * add_nic_rule() -- insert a rule entry at the head of nic_rule_list.
        !          1279:  */
        !          1280: void
        !          1281: add_nic_rule(
        !          1282:        nic_rule_match  match_type,
        !          1283:        const char *    if_name,        /* interface name or numeric address */
        !          1284:        int             prefixlen,
        !          1285:        nic_rule_action action
        !          1286:        )
        !          1287: {
        !          1288:        nic_rule *      rule;
        !          1289:        isc_boolean_t   is_ip;
        !          1290: 
        !          1291:        rule = emalloc(sizeof(*rule));
        !          1292:        memset(rule, 0, sizeof(*rule));
        !          1293:        rule->match_type = match_type;
        !          1294:        rule->prefixlen = prefixlen;
        !          1295:        rule->action = action;
        !          1296:        
        !          1297:        if (MATCH_IFNAME == match_type) {
        !          1298:                NTP_REQUIRE(NULL != if_name);
        !          1299:                rule->if_name = estrdup(if_name);
        !          1300:        } else if (MATCH_IFADDR == match_type) {
        !          1301:                NTP_REQUIRE(NULL != if_name);
        !          1302:                /* set rule->addr */
        !          1303:                is_ip = is_ip_address(if_name, &rule->addr);
        !          1304:                NTP_REQUIRE(is_ip);
        !          1305:        } else
        !          1306:                NTP_REQUIRE(NULL == if_name);
        !          1307: 
        !          1308:        LINK_SLIST(nic_rule_list, rule, next);
        !          1309: }
        !          1310: 
        !          1311: 
        !          1312: #ifdef DEBUG
        !          1313: static const char *
        !          1314: action_text(
        !          1315:        nic_rule_action action
        !          1316:        )
        !          1317: {
        !          1318:        const char *t;
        !          1319: 
        !          1320:        switch (action) {
        !          1321: 
        !          1322:        default:
        !          1323:                t = "ERROR";    /* quiet uninit warning */
        !          1324:                DPRINTF(1, ("fatal: unknown nic_rule_action %d\n",
        !          1325:                            action));
        !          1326:                NTP_ENSURE(0);
        !          1327:                break;
        !          1328: 
        !          1329:        case ACTION_LISTEN:
        !          1330:                t = "listen";
        !          1331:                break;
        !          1332: 
        !          1333:        case ACTION_IGNORE:
        !          1334:                t = "ignore";
        !          1335:                break;
        !          1336: 
        !          1337:        case ACTION_DROP:
        !          1338:                t = "drop";
        !          1339:                break;
        !          1340:        }
        !          1341: 
        !          1342:        return t;
        !          1343: }
        !          1344: #endif /* DEBUG */
        !          1345: 
        !          1346: 
        !          1347: static nic_rule_action
        !          1348: interface_action(
        !          1349:        char *          if_name,
        !          1350:        sockaddr_u *    if_addr,
        !          1351:        u_int32         if_flags
        !          1352:        )
        !          1353: {
        !          1354:        nic_rule *      rule;
        !          1355:        int             isloopback;
        !          1356:        int             iswildcard;
        !          1357: 
        !          1358:        DPRINTF(4, ("interface_action: %s %s ",
        !          1359:                    (if_name != NULL)
        !          1360:                        ? if_name
        !          1361:                        : "wildcard",
        !          1362:                    stoa(if_addr)));
        !          1363: 
        !          1364:        iswildcard = is_wildcard_addr(if_addr);
        !          1365: 
        !          1366:        /*
        !          1367:         * Always listen on 127.0.0.1 - required by ntp_intres
        !          1368:         */
        !          1369:        if (INT_LOOPBACK & if_flags) {
        !          1370:                isloopback = TRUE;
        !          1371:                if (IS_IPV4(if_addr)) {
        !          1372:                        DPRINTF(4, ("IPv4 loopback - listen\n"));
        !          1373:                        return ACTION_LISTEN;
        !          1374:                }
        !          1375:        } else {
        !          1376:                isloopback = FALSE;
        !          1377:        }
        !          1378: 
        !          1379:        /*
        !          1380:         * Find any matching NIC rule from --interface / -I or ntp.conf
        !          1381:         * interface/nic rules.
        !          1382:         */
        !          1383:        for (rule = nic_rule_list; rule != NULL; rule = rule->next) {
        !          1384: 
        !          1385:                switch (rule->match_type) {
        !          1386: 
        !          1387:                case MATCH_ALL:
        !          1388:                        /* loopback and wildcard excluded from "all" */
        !          1389:                        if (isloopback || iswildcard)
        !          1390:                                break;
        !          1391:                        DPRINTF(4, ("nic all %s\n",
        !          1392:                            action_text(rule->action)));
        !          1393:                        return rule->action;
        !          1394: 
        !          1395:                case MATCH_IPV4:
        !          1396:                        if (IS_IPV4(if_addr)) {
        !          1397:                                DPRINTF(4, ("nic ipv4 %s\n",
        !          1398:                                    action_text(rule->action)));
        !          1399:                                return rule->action;
        !          1400:                        }
        !          1401:                        break;
        !          1402: 
        !          1403:                case MATCH_IPV6:
        !          1404:                        if (IS_IPV6(if_addr)) {
        !          1405:                                DPRINTF(4, ("nic ipv6 %s\n",
        !          1406:                                    action_text(rule->action)));
        !          1407:                                return rule->action;
        !          1408:                        }
        !          1409:                        break;
        !          1410: 
        !          1411:                case MATCH_WILDCARD:
        !          1412:                        if (iswildcard) {
        !          1413:                                DPRINTF(4, ("nic wildcard %s\n",
        !          1414:                                    action_text(rule->action)));
        !          1415:                                return rule->action;
        !          1416:                        }
        !          1417:                        break;
        !          1418: 
        !          1419:                case MATCH_IFADDR:
        !          1420:                        if (rule->prefixlen != -1) {
        !          1421:                                if (addr_eqprefix(if_addr, &rule->addr,
        !          1422:                                                  rule->prefixlen)) {
        !          1423: 
        !          1424:                                        DPRINTF(4, ("subnet address match - %s\n",
        !          1425:                                            action_text(rule->action)));
        !          1426:                                        return rule->action;
        !          1427:                                }
        !          1428:                        } else
        !          1429:                                if (SOCK_EQ(if_addr, &rule->addr)) {
        !          1430: 
        !          1431:                                        DPRINTF(4, ("address match - %s\n",
        !          1432:                                            action_text(rule->action)));
        !          1433:                                        return rule->action;
        !          1434:                                }
        !          1435:                        break;
        !          1436: 
        !          1437:                case MATCH_IFNAME:
        !          1438:                        if (if_name != NULL
        !          1439:                            && !strcasecmp(if_name, rule->if_name)) {
        !          1440: 
        !          1441:                                DPRINTF(4, ("interface name match - %s\n",
        !          1442:                                    action_text(rule->action)));
        !          1443:                                return rule->action;
        !          1444:                        }
        !          1445:                        break;
        !          1446:                }
        !          1447:        }
        !          1448: 
        !          1449:        /*
        !          1450:         * Unless explicitly disabled such as with "nic ignore ::1"
        !          1451:         * listen on loopback addresses.  Since ntpq and ntpdc query
        !          1452:         * "localhost" by default, which typically resolves to ::1 and
        !          1453:         * 127.0.0.1, it's useful to default to listening on both.
        !          1454:         */
        !          1455:        if (isloopback) {
        !          1456:                DPRINTF(4, ("default loopback listen\n"));
        !          1457:                return ACTION_LISTEN;
        !          1458:        }
        !          1459: 
        !          1460:        /*
        !          1461:         * Treat wildcard addresses specially.  If there is no explicit
        !          1462:         * "nic ... wildcard" or "nic ... 0.0.0.0" or "nic ... ::" rule
        !          1463:         * default to drop.
        !          1464:         */
        !          1465:        if (iswildcard) {
        !          1466:                DPRINTF(4, ("default wildcard drop\n"));
        !          1467:                return ACTION_DROP;
        !          1468:        }
        !          1469: 
        !          1470:        /*
        !          1471:         * Check for "virtual IP" (colon in the interface name) after
        !          1472:         * the rules so that "ntpd --interface eth0:1 -novirtualips"
        !          1473:         * does indeed listen on eth0:1's addresses.
        !          1474:         */
        !          1475:        if (!listen_to_virtual_ips && if_name != NULL
        !          1476:            && (strchr(if_name, ':') != NULL)) {
        !          1477: 
        !          1478:                DPRINTF(4, ("virtual ip - ignore\n"));
        !          1479:                return ACTION_IGNORE;
        !          1480:        }
        !          1481: 
        !          1482:        /*
        !          1483:         * If there are no --interface/-I command-line options and no
        !          1484:         * interface/nic rules in ntp.conf, the default action is to
        !          1485:         * listen.  In the presence of rules from either, the default
        !          1486:         * is to ignore.  This implements ntpd's traditional listen-
        !          1487:         * every default with no interface listen configuration, and
        !          1488:         * ensures a single -I eth0 or "nic listen eth0" means do not
        !          1489:         * listen on any other addresses.
        !          1490:         */
        !          1491:        if (NULL == nic_rule_list) {
        !          1492:                DPRINTF(4, ("default listen\n"));
        !          1493:                return ACTION_LISTEN;
        !          1494:        }
        !          1495: 
        !          1496:        DPRINTF(4, ("implicit ignore\n"));
        !          1497:        return ACTION_IGNORE;
        !          1498: }
        !          1499: 
        !          1500: 
        !          1501: static void
        !          1502: convert_isc_if(
        !          1503:        isc_interface_t *isc_if,
        !          1504:        endpt *itf,
        !          1505:        u_short port
        !          1506:        )
        !          1507: {
        !          1508:        const u_char v6loop[16] = {0, 0, 0, 0, 0, 0, 0, 0,
        !          1509:                                   0, 0, 0, 0, 0, 0, 0, 1};
        !          1510: 
        !          1511:        strncpy(itf->name, isc_if->name, sizeof(itf->name));
        !          1512:        itf->name[sizeof(itf->name) - 1] = 0; /* strncpy may not */
        !          1513:        itf->ifindex = isc_if->ifindex;
        !          1514:        itf->family = (u_short)isc_if->af;
        !          1515:        AF(&itf->sin) = itf->family;
        !          1516:        AF(&itf->mask) = itf->family;
        !          1517:        AF(&itf->bcast) = itf->family;
        !          1518:        SET_PORT(&itf->sin, port);
        !          1519:        SET_PORT(&itf->mask, port);
        !          1520:        SET_PORT(&itf->bcast, port);
        !          1521: 
        !          1522:        if (IS_IPV4(&itf->sin)) {
        !          1523:                NSRCADR(&itf->sin) = isc_if->address.type.in.s_addr;
        !          1524:                NSRCADR(&itf->mask) = isc_if->netmask.type.in.s_addr;
        !          1525: 
        !          1526:                if (isc_if->flags & INTERFACE_F_BROADCAST) {
        !          1527:                        itf->flags |= INT_BROADCAST;
        !          1528:                        NSRCADR(&itf->bcast) = 
        !          1529:                            isc_if->broadcast.type.in.s_addr;
        !          1530:                }
        !          1531:        }
        !          1532: #ifdef INCLUDE_IPV6_SUPPORT
        !          1533:        else if (IS_IPV6(&itf->sin)) {
        !          1534:                SET_ADDR6N(&itf->sin, isc_if->address.type.in6);
        !          1535:                SET_ADDR6N(&itf->mask, isc_if->netmask.type.in6);
        !          1536: 
        !          1537:                SET_SCOPE(&itf->sin, isc_if->address.zone);
        !          1538:        }
        !          1539: #endif /* INCLUDE_IPV6_SUPPORT */
        !          1540: 
        !          1541: 
        !          1542:        /* Process the rest of the flags */
        !          1543: 
        !          1544:        itf->flags |=
        !          1545:                  ((INTERFACE_F_UP & isc_if->flags)
        !          1546:                        ? INT_UP : 0)
        !          1547:                | ((INTERFACE_F_LOOPBACK & isc_if->flags) 
        !          1548:                        ? INT_LOOPBACK : 0)
        !          1549:                | ((INTERFACE_F_POINTTOPOINT & isc_if->flags) 
        !          1550:                        ? INT_PPP : 0)
        !          1551:                | ((INTERFACE_F_MULTICAST & isc_if->flags) 
        !          1552:                        ? INT_MULTICAST : 0)
        !          1553:                | ((INTERFACE_F_PRIVACY & isc_if->flags)
        !          1554:                        ? INT_PRIVACY : 0)
        !          1555:                ;
        !          1556: 
        !          1557:        /*
        !          1558:         * Clear the loopback flag if the address is not localhost.
        !          1559:         * http://bugs.ntp.org/1683
        !          1560:         */
        !          1561:        if (INT_LOOPBACK & itf->flags) {
        !          1562:                if (AF_INET == itf->family) {
        !          1563:                        if (127 != (SRCADR(&itf->sin) >> 24))
        !          1564:                                itf->flags &= ~INT_LOOPBACK;
        !          1565:                } else {
        !          1566:                        if (memcmp(v6loop, NSRCADR6(&itf->sin),
        !          1567:                                   sizeof(NSRCADR6(&itf->sin))))
        !          1568:                                itf->flags &= ~INT_LOOPBACK;
        !          1569:                }
        !          1570:        }
        !          1571: }
        !          1572: 
        !          1573: 
        !          1574: /*
        !          1575:  * refresh_interface
        !          1576:  *
        !          1577:  * some OSes have been observed to keep
        !          1578:  * cached routes even when more specific routes
        !          1579:  * become available.
        !          1580:  * this can be mitigated by re-binding
        !          1581:  * the socket.
        !          1582:  */
        !          1583: static int
        !          1584: refresh_interface(
        !          1585:        struct interface * interface
        !          1586:        )
        !          1587: {
        !          1588: #ifdef  OS_MISSES_SPECIFIC_ROUTE_UPDATES
        !          1589:        if (interface->fd != INVALID_SOCKET) {
        !          1590:                close_and_delete_fd_from_list(interface->fd);
        !          1591:                interface->fd = open_socket(&interface->sin,
        !          1592:                                            0, 0, interface);
        !          1593:                 /*
        !          1594:                  * reset TTL indication so TTL is is set again 
        !          1595:                  * next time around
        !          1596:                  */
        !          1597:                interface->last_ttl = 0;
        !          1598:                return (interface->fd != INVALID_SOCKET);
        !          1599:        } else
        !          1600:                return 0;       /* invalid sockets are not refreshable */
        !          1601: #else /* !OS_MISSES_SPECIFIC_ROUTE_UPDATES */
        !          1602:        return (interface->fd != INVALID_SOCKET);
        !          1603: #endif /* !OS_MISSES_SPECIFIC_ROUTE_UPDATES */
        !          1604: }
        !          1605: 
        !          1606: /*
        !          1607:  * interface_update - externally callable update function
        !          1608:  */
        !          1609: void
        !          1610: interface_update(
        !          1611:        interface_receiver_t    receiver,
        !          1612:        void *                  data)
        !          1613: {
        !          1614:        int new_interface_found;
        !          1615: 
        !          1616:        if (disable_dynamic_updates)
        !          1617:                return;
        !          1618: 
        !          1619:        BLOCKIO();
        !          1620:        new_interface_found = update_interfaces(NTP_PORT, receiver, data);
        !          1621:        UNBLOCKIO();
        !          1622: 
        !          1623:        if (!new_interface_found)
        !          1624:                return;
        !          1625: 
        !          1626: #ifdef DEBUG
        !          1627:        msyslog(LOG_DEBUG, "new interface(s) found: waking up resolver");
        !          1628: #endif
        !          1629: #ifdef SYS_WINNT
        !          1630:        /* wake up the resolver thread */
        !          1631:        if (ResolverEventHandle != NULL)
        !          1632:                SetEvent(ResolverEventHandle);
        !          1633: #else
        !          1634:        /* write any single byte to the pipe to wake up the resolver process */
        !          1635:        write( resolver_pipe_fd[1], &new_interface_found, 1 );
        !          1636: #endif
        !          1637: }
        !          1638: 
        !          1639: 
        !          1640: /*
        !          1641:  * sau_from_netaddr() - convert network address on-wire formats.
        !          1642:  * Convert from libisc's isc_netaddr_t to NTP's sockaddr_u
        !          1643:  */
        !          1644: void
        !          1645: sau_from_netaddr(
        !          1646:        sockaddr_u *psau,
        !          1647:        const isc_netaddr_t *pna
        !          1648:        )
        !          1649: {
        !          1650:        memset(psau, 0, sizeof(*psau));
        !          1651:        AF(psau) = (u_short)pna->family;
        !          1652:        switch (pna->family) {
        !          1653: 
        !          1654:        case AF_INET:
        !          1655:                memcpy(&psau->sa4.sin_addr, &pna->type.in,
        !          1656:                       sizeof(psau->sa4.sin_addr));
        !          1657:                break;
        !          1658: 
        !          1659:        case AF_INET6:
        !          1660:                memcpy(&psau->sa6.sin6_addr, &pna->type.in6,
        !          1661:                       sizeof(psau->sa6.sin6_addr));
        !          1662:                break;
        !          1663:        }
        !          1664: }
        !          1665: 
        !          1666: 
        !          1667: static int
        !          1668: is_wildcard_addr(
        !          1669:        const sockaddr_u *psau
        !          1670:        )
        !          1671: {
        !          1672:        if (IS_IPV4(psau) && !NSRCADR(psau))
        !          1673:                return 1;
        !          1674: 
        !          1675: #ifdef INCLUDE_IPV6_SUPPORT
        !          1676:        if (IS_IPV6(psau) && S_ADDR6_EQ(psau, &in6addr_any))
        !          1677:                return 1;
        !          1678: #endif
        !          1679: 
        !          1680:        return 0;
        !          1681: }
        !          1682: 
        !          1683: 
        !          1684: #ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND
        !          1685: /*
        !          1686:  * enable/disable re-use of wildcard address socket
        !          1687:  */
        !          1688: static void
        !          1689: set_wildcard_reuse(
        !          1690:        u_short family,
        !          1691:        int     on
        !          1692:        )
        !          1693: {
        !          1694:        struct interface *any;
        !          1695:        SOCKET fd = INVALID_SOCKET;
        !          1696: 
        !          1697:        any = ANY_INTERFACE_BYFAM(family);
        !          1698:        if (any != NULL)
        !          1699:                fd = any->fd;
        !          1700: 
        !          1701:        if (fd != INVALID_SOCKET) {
        !          1702:                if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
        !          1703:                               (char *)&on, sizeof(on)))
        !          1704:                        msyslog(LOG_ERR,
        !          1705:                                "set_wildcard_reuse: setsockopt(SO_REUSEADDR, %s) failed: %m",
        !          1706:                                on ? "on" : "off");
        !          1707: 
        !          1708:                DPRINTF(4, ("set SO_REUSEADDR to %s on %s\n", 
        !          1709:                            on ? "on" : "off",
        !          1710:                            stoa(&any->sin)));
        !          1711:        }
        !          1712: }
        !          1713: #endif /* OS_NEEDS_REUSEADDR_FOR_IFADDRBIND */
        !          1714: 
        !          1715: 
        !          1716: static isc_boolean_t
        !          1717: is_anycast(
        !          1718:        sockaddr_u *psau,
        !          1719:        const char *name
        !          1720:        )
        !          1721: {
        !          1722: #if defined(INCLUDE_IPV6_SUPPORT) && defined(SIOCGIFAFLAG_IN6) && \
        !          1723:     defined(IN6_IFF_ANYCAST)
        !          1724:        struct in6_ifreq ifr6;
        !          1725:        int fd;
        !          1726:        u_int32 flags6;
        !          1727: 
        !          1728:        if (psau->sa.sa_family != AF_INET6)
        !          1729:                return ISC_FALSE;
        !          1730:        if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
        !          1731:                return ISC_FALSE;
        !          1732:        memset(&ifr6, 0, sizeof(ifr6));
        !          1733:        memcpy(&ifr6.ifr_addr, &psau->sa6, sizeof(ifr6.ifr_addr));
        !          1734:        strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
        !          1735:        if (ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
        !          1736:                close(fd);
        !          1737:                return ISC_FALSE;
        !          1738:        }
        !          1739:        close(fd);
        !          1740:        flags6 = ifr6.ifr_ifru.ifru_flags6;
        !          1741:        if ((flags6 & IN6_IFF_ANYCAST) != 0)
        !          1742:                return ISC_TRUE;
        !          1743: #endif /* INCLUDE_IPV6_SUPPORT && SIOCGIFAFLAG_IN6 && IN6_IFF_ANYCAST */
        !          1744:        return ISC_FALSE;
        !          1745: }
        !          1746: 
        !          1747: 
        !          1748: /*
        !          1749:  * update_interface strategy
        !          1750:  *
        !          1751:  * toggle configuration phase
        !          1752:  *
        !          1753:  * Phase 1:
        !          1754:  * forall currently existing interfaces
        !          1755:  *   if address is known:
        !          1756:  *     drop socket - rebind again
        !          1757:  *
        !          1758:  *   if address is NOT known:
        !          1759:  *     attempt to create a new interface entry
        !          1760:  *
        !          1761:  * Phase 2:
        !          1762:  * forall currently known non MCAST and WILDCARD interfaces
        !          1763:  *   if interface does not match configuration phase (not seen in phase 1):
        !          1764:  *     remove interface from known interface list
        !          1765:  *     forall peers associated with this interface
        !          1766:  *         disconnect peer from this interface
        !          1767:  *
        !          1768:  * Phase 3:
        !          1769:  *   attempt to re-assign interfaces to peers
        !          1770:  *
        !          1771:  */
        !          1772: 
        !          1773: static int
        !          1774: update_interfaces(
        !          1775:        u_short                 port,
        !          1776:        interface_receiver_t    receiver,
        !          1777:        void *                  data
        !          1778:        )
        !          1779: {
        !          1780:        isc_mem_t *             mctx = (void *)-1;
        !          1781:        interface_info_t        ifi;
        !          1782:        isc_interfaceiter_t *   iter;
        !          1783:        isc_result_t            result;
        !          1784:        isc_interface_t         isc_if;
        !          1785:        int                     new_interface_found;
        !          1786:        int                     refresh_peers;
        !          1787:        unsigned int            family;
        !          1788:        endpt                   enumep;
        !          1789:        endpt *                 ep;
        !          1790:        endpt *                 next_ep;
        !          1791: 
        !          1792:        DPRINTF(3, ("update_interfaces(%d)\n", port));
        !          1793: 
        !          1794:        /*
        !          1795:         * phase one - scan interfaces
        !          1796:         * - create those that are not found
        !          1797:         * - update those that are found
        !          1798:         */
        !          1799: 
        !          1800:        new_interface_found = FALSE;
        !          1801:        refresh_peers = FALSE;
        !          1802:        iter = NULL;
        !          1803:        result = isc_interfaceiter_create(mctx, &iter);
        !          1804: 
        !          1805:        if (result != ISC_R_SUCCESS)
        !          1806:                return 0;
        !          1807: 
        !          1808:        /* 
        !          1809:         * Toggle system interface scan phase to find untouched
        !          1810:         * interfaces to be deleted.
        !          1811:         */
        !          1812:        sys_interphase ^= 0x1;
        !          1813:        
        !          1814:        for (result = isc_interfaceiter_first(iter);
        !          1815:             ISC_R_SUCCESS == result;
        !          1816:             result = isc_interfaceiter_next(iter)) {
        !          1817: 
        !          1818:                result = isc_interfaceiter_current(iter, &isc_if);
        !          1819: 
        !          1820:                if (result != ISC_R_SUCCESS)
        !          1821:                        break;
        !          1822: 
        !          1823:                /* See if we have a valid family to use */
        !          1824:                family = isc_if.address.family;
        !          1825:                if (AF_INET != family && AF_INET6 != family)
        !          1826:                        continue;
        !          1827:                if (AF_INET == family && !ipv4_works)
        !          1828:                        continue;
        !          1829:                if (AF_INET6 == family && !ipv6_works)
        !          1830:                        continue;
        !          1831: 
        !          1832:                /* create prototype */
        !          1833:                init_interface(&enumep);
        !          1834: 
        !          1835:                convert_isc_if(&isc_if, &enumep, port);
        !          1836: 
        !          1837:                /* 
        !          1838:                 * Check if and how we are going to use the interface.
        !          1839:                 */
        !          1840:                switch (interface_action(enumep.name, &enumep.sin,
        !          1841:                                         enumep.flags)) {
        !          1842: 
        !          1843:                case ACTION_IGNORE:
        !          1844:                        continue;
        !          1845: 
        !          1846:                case ACTION_LISTEN:
        !          1847:                        enumep.ignore_packets = ISC_FALSE;
        !          1848:                        break;
        !          1849: 
        !          1850:                case ACTION_DROP:
        !          1851:                        enumep.ignore_packets = ISC_TRUE;
        !          1852:                        break;
        !          1853:                }
        !          1854: 
        !          1855:                DPRINT_INTERFACE(4, (&enumep, "examining ", "\n"));
        !          1856: 
        !          1857:                 /* interfaces must be UP to be usable */
        !          1858:                if (!(enumep.flags & INT_UP)) {
        !          1859:                        DPRINTF(4, ("skipping interface %s (%s) - DOWN\n",
        !          1860:                                    enumep.name, stoa(&enumep.sin)));
        !          1861:                        continue;
        !          1862:                }
        !          1863: 
        !          1864:                /*
        !          1865:                 * skip any interfaces UP and bound to a wildcard
        !          1866:                 * address - some dhcp clients produce that in the
        !          1867:                 * wild
        !          1868:                 */
        !          1869:                if (is_wildcard_addr(&enumep.sin))
        !          1870:                        continue;
        !          1871: 
        !          1872:                if (is_anycast(&enumep.sin, isc_if.name))
        !          1873:                        continue;
        !          1874: 
        !          1875:                /*
        !          1876:                 * map to local *address* in order to map all duplicate
        !          1877:                 * interfaces to an endpt structure with the appropriate
        !          1878:                 * socket.  Our name space is (ip-address), NOT
        !          1879:                 * (interface name, ip-address).
        !          1880:                 */
        !          1881:                ep = getinterface(&enumep.sin, INT_WILDCARD);
        !          1882:                
        !          1883:                if (ep != NULL && refresh_interface(ep)) {
        !          1884:                        /*
        !          1885:                         * found existing and up to date interface -
        !          1886:                         * mark present.
        !          1887:                         */
        !          1888:                        if (ep->phase != sys_interphase) {
        !          1889:                                /*
        !          1890:                                 * On a new round we reset the name so
        !          1891:                                 * the interface name shows up again if
        !          1892:                                 * this address is no longer shared.
        !          1893:                                 * We reset ignore_packets from the
        !          1894:                                 * new prototype to respect any runtime
        !          1895:                                 * changes to the nic rules.
        !          1896:                                 */
        !          1897:                                strncpy(ep->name, enumep.name,
        !          1898:                                        sizeof(ep->name));
        !          1899:                                if (ep->ignore_packets !=
        !          1900:                                    enumep.ignore_packets) {
        !          1901:                                        ep->ignore_packets = 
        !          1902:                                            enumep.ignore_packets;
        !          1903:                                        refresh_peers = TRUE;
        !          1904:                                        DPRINTF(4, ("refreshing peers due to %s ignore_packets change to %d\n",
        !          1905:                                            stoa(&ep->sin),
        !          1906:                                            ep->ignore_packets));
        !          1907:                                }
        !          1908:                        } else {
        !          1909:                                /* name collision - rename interface */
        !          1910:                                strncpy(ep->name, "*multiple*",
        !          1911:                                        sizeof(ep->name));
        !          1912:                        }
        !          1913: 
        !          1914:                        DPRINT_INTERFACE(4, (ep, "updating ", 
        !          1915:                                             " present\n"));
        !          1916: 
        !          1917:                        if (ep->ignore_packets !=
        !          1918:                            enumep.ignore_packets) {
        !          1919:                                /*
        !          1920:                                 * We have conflicting configurations
        !          1921:                                 * for the interface address. This is
        !          1922:                                 * caused by using -I <interfacename>
        !          1923:                                 * for an interface that shares its 
        !          1924:                                 * address with other interfaces. We
        !          1925:                                 * can not disambiguate incoming
        !          1926:                                 * packets delivered to this socket
        !          1927:                                 * without extra syscalls/features.
        !          1928:                                 * These are not (commonly) available.
        !          1929:                                 * Note this is a more unusual
        !          1930:                                 * configuration where several
        !          1931:                                 * interfaces share an address but
        !          1932:                                 * filtering via interface name is
        !          1933:                                 * attempted.  We resolve the
        !          1934:                                 * configuration conflict by disabling
        !          1935:                                 * the processing of received packets.
        !          1936:                                 * This leads to no service on the
        !          1937:                                 * interface address where the conflict
        !          1938:                                 * occurs.
        !          1939:                                 */
        !          1940:                                msyslog(LOG_ERR,
        !          1941:                                        "WARNING: conflicting enable configuration for interfaces %s and %s for address %s - unsupported configuration - address DISABLED",
        !          1942:                                        enumep.name, ep->name,
        !          1943:                                        stoa(&enumep.sin));
        !          1944: 
        !          1945:                                ep->ignore_packets = ISC_TRUE;                          
        !          1946:                        }
        !          1947: 
        !          1948:                        ep->phase = sys_interphase;
        !          1949: 
        !          1950:                        ifi.action = IFS_EXISTS;
        !          1951:                        ifi.ep = ep;
        !          1952:                        if (receiver != NULL)
        !          1953:                                (*receiver)(data, &ifi);
        !          1954:                } else {
        !          1955:                        /*
        !          1956:                         * This is new or refreshing failed - add to
        !          1957:                         * our interface list.  If refreshing failed we
        !          1958:                         * will delete the interface structure in phase
        !          1959:                         * 2 as the interface was not marked current.
        !          1960:                         * We can bind to the address as the refresh
        !          1961:                         * code already closed the offending socket
        !          1962:                         */
        !          1963:                        ep = create_interface(port, &enumep);
        !          1964: 
        !          1965:                        if (ep != NULL) {
        !          1966:                                ifi.action = IFS_CREATED;
        !          1967:                                ifi.ep = ep;
        !          1968:                                if (receiver != NULL)
        !          1969:                                        (*receiver)(data, &ifi);
        !          1970: 
        !          1971:                                new_interface_found = TRUE;
        !          1972:                                refresh_peers = TRUE;
        !          1973:                                DPRINTF(4, ("refreshing peers due to new addr %s\n",
        !          1974:                                        stoa(&ep->sin)));
        !          1975:                                DPRINT_INTERFACE(3,
        !          1976:                                        (ep, "updating ",
        !          1977:                                         " new - created\n"));
        !          1978:                        } else {
        !          1979:                                DPRINT_INTERFACE(3, 
        !          1980:                                        (&enumep, "updating ",
        !          1981:                                         " new - creation FAILED"));
        !          1982:                        
        !          1983:                                msyslog(LOG_INFO,
        !          1984:                                        "failed to init interface for address %s", 
        !          1985:                                        stoa(&enumep.sin));
        !          1986:                                continue;
        !          1987:                        }
        !          1988:                }
        !          1989:        }
        !          1990: 
        !          1991:        isc_interfaceiter_destroy(&iter);
        !          1992: 
        !          1993:        /*
        !          1994:         * phase 2 - delete gone interfaces - reassigning peers to
        !          1995:         * other interfaces
        !          1996:         */
        !          1997:        for (ep = ep_list; ep != NULL; ep = next_ep) {
        !          1998:                next_ep = ep->elink;
        !          1999:                  
        !          2000:                /*
        !          2001:                 * if phase does not match sys_phase this interface was
        !          2002:                 * not enumerated during the last interface scan - so it
        !          2003:                 * is gone and will be deleted here unless it did not
        !          2004:                 * originate from interface enumeration (INT_WILDCARD,
        !          2005:                 * INT_MCASTIF).
        !          2006:                 */
        !          2007:                if (((INT_WILDCARD | INT_MCASTIF) & ep->flags) ||
        !          2008:                    ep->phase == sys_interphase)
        !          2009:                        continue;
        !          2010: 
        !          2011:                DPRINT_INTERFACE(3, (ep, "updating ",
        !          2012:                                     "GONE - deleting\n"));
        !          2013:                remove_interface(ep);
        !          2014:                refresh_peers = TRUE;
        !          2015:                DPRINTF(4, ("refreshing peers due to deleted addr %s",
        !          2016:                            stoa(&ep->sin)));
        !          2017: 
        !          2018:                ifi.action = IFS_DELETED;
        !          2019:                ifi.ep = ep;
        !          2020:                if (receiver != NULL)
        !          2021:                        (*receiver)(data, &ifi);
        !          2022: 
        !          2023:                /* disconnect peers from deleted endpt. */
        !          2024:                while (ep->peers != NULL)
        !          2025:                        set_peerdstadr(ep->peers, NULL);
        !          2026: 
        !          2027:                /*
        !          2028:                 * update globals in case we lose 
        !          2029:                 * a loopback interface
        !          2030:                 */
        !          2031:                if (ep == loopback_interface)
        !          2032:                        loopback_interface = NULL;
        !          2033: 
        !          2034:                delete_interface(ep);
        !          2035:        }
        !          2036: 
        !          2037:        /*
        !          2038:         * phase 3 - re-configure as the world has changed if necessary
        !          2039:         */
        !          2040:        if (refresh_peers) {
        !          2041:                refresh_all_peerinterfaces();
        !          2042:                msyslog(LOG_INFO, "peers refreshed");
        !          2043:        }
        !          2044: 
        !          2045:        return new_interface_found;
        !          2046: }
        !          2047: 
        !          2048: 
        !          2049: /*
        !          2050:  * create_sockets - create a socket for each interface plus a default
        !          2051:  *                     socket for when we don't know where to send
        !          2052:  */
        !          2053: static int
        !          2054: create_sockets(
        !          2055:        u_short port
        !          2056:        )
        !          2057: {
        !          2058: #ifndef HAVE_IO_COMPLETION_PORT
        !          2059:        /*
        !          2060:         * I/O Completion Ports don't care about the select and FD_SET
        !          2061:         */
        !          2062:        maxactivefd = 0;
        !          2063:        FD_ZERO(&activefds);
        !          2064: #endif
        !          2065: 
        !          2066:        DPRINTF(2, ("create_sockets(%d)\n", port));
        !          2067: 
        !          2068:        create_wildcards(port);
        !          2069: 
        !          2070:        update_interfaces(port, NULL, NULL);
        !          2071:        
        !          2072:        /*
        !          2073:         * Now that we have opened all the sockets, turn off the reuse
        !          2074:         * flag for security.
        !          2075:         */
        !          2076:        set_reuseaddr(0);
        !          2077: 
        !          2078:        DPRINTF(2, ("create_sockets: Total interfaces = %d\n", ninterfaces));
        !          2079: 
        !          2080:        return ninterfaces;
        !          2081: }
        !          2082: 
        !          2083: /*
        !          2084:  * create_interface - create a new interface for a given prototype
        !          2085:  *                   binding the socket.
        !          2086:  */
        !          2087: static struct interface *
        !          2088: create_interface(
        !          2089:        u_short                 port,
        !          2090:        struct interface *      protot
        !          2091:        )
        !          2092: {
        !          2093:        sockaddr_u      resmask;
        !          2094:        endpt *         iface;
        !          2095: #if defined(MCAST) && defined(MULTICAST_NONEWSOCKET)
        !          2096:        remaddr_t *     entry;
        !          2097:        remaddr_t *     next_entry;
        !          2098: #endif
        !          2099:        DPRINTF(2, ("create_interface(%s#%d)\n", stoa(&protot->sin),
        !          2100:                    port));
        !          2101: 
        !          2102:        /* build an interface */
        !          2103:        iface = new_interface(protot);
        !          2104:        
        !          2105:        /*
        !          2106:         * create socket
        !          2107:         */
        !          2108:        iface->fd = open_socket(&iface->sin, 0, 0, iface);
        !          2109: 
        !          2110:        if (iface->fd != INVALID_SOCKET)
        !          2111:                log_listen_address(iface);
        !          2112: 
        !          2113:        if ((INT_BROADCAST & iface->flags)
        !          2114:            && iface->bfd != INVALID_SOCKET)
        !          2115:                msyslog(LOG_INFO, "Listening on broadcast address %s#%d",
        !          2116:                        stoa((&iface->bcast)), port);
        !          2117: 
        !          2118:        if (INVALID_SOCKET == iface->fd
        !          2119:            && INVALID_SOCKET == iface->bfd) {
        !          2120:                msyslog(LOG_ERR, "unable to create socket on %s (%d) for %s#%d",
        !          2121:                        iface->name,
        !          2122:                        iface->ifnum,
        !          2123:                        stoa((&iface->sin)),
        !          2124:                        port);
        !          2125:                delete_interface(iface);
        !          2126:                return NULL;
        !          2127:        }
        !          2128:        
        !          2129:        /*
        !          2130:         * Blacklist our own addresses, no use talking to ourself
        !          2131:         */
        !          2132:        SET_HOSTMASK(&resmask, AF(&iface->sin));
        !          2133:        hack_restrict(RESTRICT_FLAGS, &iface->sin, &resmask,
        !          2134:                      RESM_NTPONLY | RESM_INTERFACE, RES_IGNORE);
        !          2135:          
        !          2136:        /*
        !          2137:         * set globals with the first found
        !          2138:         * loopback interface of the appropriate class
        !          2139:         */
        !          2140:        if (NULL == loopback_interface && AF_INET == iface->family
        !          2141:            && (INT_LOOPBACK & iface->flags))
        !          2142:                loopback_interface = iface;
        !          2143: 
        !          2144:        /*
        !          2145:         * put into our interface list
        !          2146:         */
        !          2147:        add_addr_to_list(&iface->sin, iface);
        !          2148:        add_interface(iface);
        !          2149: 
        !          2150: #if defined(MCAST) && defined(MULTICAST_NONEWSOCKET)
        !          2151:        /*
        !          2152:         * Join any previously-configured compatible multicast groups.
        !          2153:         */
        !          2154:        if (INT_MULTICAST & iface->flags &&
        !          2155:            !((INT_LOOPBACK | INT_WILDCARD) & iface->flags) &&
        !          2156:            !iface->ignore_packets) {
        !          2157:                for (entry = remoteaddr_list;
        !          2158:                     entry != NULL;
        !          2159:                     entry = next_entry) {
        !          2160:                        next_entry = entry->link;
        !          2161:                        if (AF(&iface->sin) != AF(&entry->addr) ||
        !          2162:                            !IS_MCAST(&entry->addr))
        !          2163:                                continue;
        !          2164:                        if (socket_multicast_enable(iface,
        !          2165:                                                    &entry->addr))
        !          2166:                                msyslog(LOG_INFO, 
        !          2167:                                        "Joined %s socket to multicast group %s",
        !          2168:                                        stoa(&iface->sin),
        !          2169:                                        stoa(&entry->addr));
        !          2170:                        else
        !          2171:                                msyslog(LOG_ERR,
        !          2172:                                        "Failed to join %s socket to multicast group %s",
        !          2173:                                        stoa(&iface->sin),
        !          2174:                                        stoa(&entry->addr));
        !          2175:                }
        !          2176:        }
        !          2177: #endif /* MCAST && MCAST_NONEWSOCKET */
        !          2178: 
        !          2179:        DPRINT_INTERFACE(2, (iface, "created ", "\n"));
        !          2180:        return iface;
        !          2181: }
        !          2182: 
        !          2183: 
        !          2184: #ifdef SO_EXCLUSIVEADDRUSE
        !          2185: static void
        !          2186: set_excladdruse(
        !          2187:        SOCKET fd
        !          2188:        )
        !          2189: {
        !          2190:        int one = 1;
        !          2191:        int failed;
        !          2192: #ifdef SYS_WINNT
        !          2193:        DWORD err;
        !          2194: #endif
        !          2195: 
        !          2196:        failed = setsockopt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
        !          2197:                            (char *)&one, sizeof(one));
        !          2198: 
        !          2199:        if (!failed)
        !          2200:                return;
        !          2201: 
        !          2202: #ifdef SYS_WINNT
        !          2203:        /*
        !          2204:         * Prior to Windows XP setting SO_EXCLUSIVEADDRUSE can fail with
        !          2205:         * error WSAINVAL depending on service pack level and whether
        !          2206:         * the user account is in the Administrators group.  Do not 
        !          2207:         * complain if it fails that way on versions prior to XP (5.1).
        !          2208:         */
        !          2209:        err = GetLastError();
        !          2210: 
        !          2211:        if (isc_win32os_versioncheck(5, 1, 0, 0) < 0    /* < 5.1/XP */
        !          2212:            && WSAEINVAL == err)
        !          2213:                return;
        !          2214: 
        !          2215:        SetLastError(err);
        !          2216: #endif
        !          2217:        msyslog(LOG_ERR, 
        !          2218:                "setsockopt(%d, SO_EXCLUSIVEADDRUSE, on): %m",
        !          2219:                (int)fd);
        !          2220: }
        !          2221: #endif  /* SO_EXCLUSIVEADDRUSE */
        !          2222: 
        !          2223: 
        !          2224: /*
        !          2225:  * set_reuseaddr() - set/clear REUSEADDR on all sockets
        !          2226:  *                     NB possible hole - should we be doing this on broadcast
        !          2227:  *                     fd's also?
        !          2228:  */
        !          2229: static void
        !          2230: set_reuseaddr(
        !          2231:        int flag
        !          2232:        )
        !          2233: {
        !          2234: #ifndef SO_EXCLUSIVEADDRUSE
        !          2235:        endpt *ep;
        !          2236: 
        !          2237:        for (ep = ep_list; ep != NULL; ep = ep->elink) {
        !          2238:                if (ep->flags & INT_WILDCARD)
        !          2239:                        continue;
        !          2240:          
        !          2241:                /*
        !          2242:                 * if ep->fd  is INVALID_SOCKET, we might have a adapter
        !          2243:                 * configured but not present
        !          2244:                 */
        !          2245:                DPRINTF(4, ("setting SO_REUSEADDR on %.16s@%s to %s\n",
        !          2246:                            ep->name, stoa(&ep->sin),
        !          2247:                            flag ? "on" : "off"));
        !          2248:                
        !          2249:                if (ep->fd != INVALID_SOCKET) {
        !          2250:                        if (setsockopt(ep->fd, SOL_SOCKET, SO_REUSEADDR,
        !          2251:                                       (char *)&flag, sizeof(flag))) {
        !          2252:                                msyslog(LOG_ERR, "set_reuseaddr: setsockopt(%s, SO_REUSEADDR, %s) failed: %m",
        !          2253:                                        stoa(&ep->sin), flag ? "on" : "off");
        !          2254:                        }
        !          2255:                }
        !          2256:        }
        !          2257: #endif /* ! SO_EXCLUSIVEADDRUSE */
        !          2258: }
        !          2259: 
        !          2260: /*
        !          2261:  * This is just a wrapper around an internal function so we can
        !          2262:  * make other changes as necessary later on
        !          2263:  */
        !          2264: void
        !          2265: enable_broadcast(
        !          2266:        struct interface *      iface, 
        !          2267:        sockaddr_u *            baddr
        !          2268:        )
        !          2269: {
        !          2270: #ifdef OPEN_BCAST_SOCKET 
        !          2271:        socket_broadcast_enable(iface, iface->fd, baddr);
        !          2272: #endif
        !          2273: }
        !          2274: 
        !          2275: #ifdef OPEN_BCAST_SOCKET 
        !          2276: /*
        !          2277:  * Enable a broadcast address to a given socket
        !          2278:  * The socket is in the inter_list all we need to do is enable
        !          2279:  * broadcasting. It is not this function's job to select the socket
        !          2280:  */
        !          2281: static isc_boolean_t
        !          2282: socket_broadcast_enable(
        !          2283:        struct interface *      iface, 
        !          2284:        SOCKET                  fd, 
        !          2285:        sockaddr_u *            baddr
        !          2286:        )
        !          2287: {
        !          2288: #ifdef SO_BROADCAST
        !          2289:        int on = 1;
        !          2290: 
        !          2291:        if (IS_IPV4(baddr)) {
        !          2292:                /* if this interface can support broadcast, set SO_BROADCAST */
        !          2293:                if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
        !          2294:                               (char *)&on, sizeof(on)))
        !          2295:                        msyslog(LOG_ERR,
        !          2296:                                "setsockopt(SO_BROADCAST) enable failure on address %s: %m",
        !          2297:                                stoa(baddr));
        !          2298:                else
        !          2299:                        DPRINTF(2, ("Broadcast enabled on socket %d for address %s\n",
        !          2300:                                    fd, stoa(baddr)));
        !          2301:        }
        !          2302:        iface->flags |= INT_BCASTOPEN;
        !          2303:        broadcast_client_enabled = ISC_TRUE;
        !          2304:        return ISC_TRUE;
        !          2305: #else
        !          2306:        return ISC_FALSE;
        !          2307: #endif /* SO_BROADCAST */
        !          2308: }
        !          2309: 
        !          2310: /*
        !          2311:  * Remove a broadcast address from a given socket
        !          2312:  * The socket is in the inter_list all we need to do is disable
        !          2313:  * broadcasting. It is not this function's job to select the socket
        !          2314:  */
        !          2315: static isc_boolean_t
        !          2316: socket_broadcast_disable(
        !          2317:        struct interface *      iface, 
        !          2318:        sockaddr_u *            baddr
        !          2319:        )
        !          2320: {
        !          2321: #ifdef SO_BROADCAST
        !          2322:        int off = 0;    /* This seems to be OK as an int */
        !          2323: 
        !          2324:        if (IS_IPV4(baddr) && setsockopt(iface->fd, SOL_SOCKET,
        !          2325:            SO_BROADCAST, (char *)&off, sizeof(off)))
        !          2326:                msyslog(LOG_ERR,
        !          2327:                        "setsockopt(SO_BROADCAST) disable failure on address %s: %m",
        !          2328:                        stoa(baddr));
        !          2329: 
        !          2330:        iface->flags &= ~INT_BCASTOPEN;
        !          2331:        broadcast_client_enabled = ISC_FALSE;
        !          2332:        return ISC_TRUE;
        !          2333: #else
        !          2334:        return ISC_FALSE;
        !          2335: #endif /* SO_BROADCAST */
        !          2336: }
        !          2337: 
        !          2338: #endif /* OPEN_BCAST_SOCKET */
        !          2339: 
        !          2340: /*
        !          2341:  * return the broadcast client flag value
        !          2342:  */
        !          2343: isc_boolean_t
        !          2344: get_broadcastclient_flag(void)
        !          2345: {
        !          2346:        return (broadcast_client_enabled);
        !          2347: }
        !          2348: /*
        !          2349:  * Check to see if the address is a multicast address
        !          2350:  */
        !          2351: static isc_boolean_t
        !          2352: addr_ismulticast(
        !          2353:        sockaddr_u *maddr
        !          2354:        )
        !          2355: {
        !          2356:        isc_boolean_t result;
        !          2357: 
        !          2358: #ifndef INCLUDE_IPV6_MULTICAST_SUPPORT
        !          2359:        /*
        !          2360:         * If we don't have IPV6 support any IPV6 addr is not multicast
        !          2361:         */
        !          2362:        if (IS_IPV6(maddr))
        !          2363:                result = ISC_FALSE;
        !          2364:        else
        !          2365: #endif
        !          2366:                result = IS_MCAST(maddr);
        !          2367: 
        !          2368:        if (!result)
        !          2369:                DPRINTF(4, ("address %s is not multicast\n",
        !          2370:                            stoa(maddr)));
        !          2371: 
        !          2372:        return result;
        !          2373: }
        !          2374: 
        !          2375: /*
        !          2376:  * Multicast servers need to set the appropriate Multicast interface
        !          2377:  * socket option in order for it to know which interface to use for
        !          2378:  * send the multicast packet.
        !          2379:  */
        !          2380: void
        !          2381: enable_multicast_if(
        !          2382:        struct interface *      iface,
        !          2383:        sockaddr_u *            maddr
        !          2384:        )
        !          2385: {
        !          2386: #ifdef MCAST
        !          2387:        TYPEOF_IP_MULTICAST_LOOP off = 0;
        !          2388: 
        !          2389:        NTP_REQUIRE(AF(maddr) == AF(&iface->sin));
        !          2390: 
        !          2391:        switch (AF(&iface->sin)) {
        !          2392: 
        !          2393:        case AF_INET:
        !          2394: #ifdef IP_MULTICAST_LOOP
        !          2395:                /*
        !          2396:                 * Don't send back to itself, but allow failure to set
        !          2397:                 */
        !          2398:                if (setsockopt(iface->fd, IPPROTO_IP,
        !          2399:                               IP_MULTICAST_LOOP,
        !          2400:                               SETSOCKOPT_ARG_CAST &off,
        !          2401:                               sizeof(off))) {
        !          2402: 
        !          2403:                        msyslog(LOG_ERR,
        !          2404:                                "setsockopt IP_MULTICAST_LOOP failed: %m on socket %d, addr %s for multicast address %s",
        !          2405:                                iface->fd, stoa(&iface->sin), 
        !          2406:                                stoa(maddr));
        !          2407:                }
        !          2408: #endif
        !          2409:                break;
        !          2410: 
        !          2411:        case AF_INET6:
        !          2412: #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
        !          2413: #ifdef IPV6_MULTICAST_LOOP
        !          2414:                /*
        !          2415:                 * Don't send back to itself, but allow failure to set
        !          2416:                 */
        !          2417:                if (setsockopt(iface->fd, IPPROTO_IPV6,
        !          2418:                               IPV6_MULTICAST_LOOP,
        !          2419:                               (char *) &off, sizeof(off))) {
        !          2420: 
        !          2421:                        msyslog(LOG_ERR,
        !          2422:                                "setsockopt IP_MULTICAST_LOOP failed: %m on socket %d, addr %s for multicast address %s",
        !          2423:                                iface->fd, stoa(&iface->sin),
        !          2424:                                stoa(maddr));
        !          2425:                }
        !          2426: #endif
        !          2427:                break;
        !          2428: #else
        !          2429:                return;
        !          2430: #endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */
        !          2431:        }
        !          2432:        return;
        !          2433: #endif
        !          2434: }
        !          2435: 
        !          2436: /*
        !          2437:  * Add a multicast address to a given socket
        !          2438:  * The socket is in the inter_list all we need to do is enable
        !          2439:  * multicasting. It is not this function's job to select the socket
        !          2440:  */
        !          2441: #if defined(MCAST)
        !          2442: static isc_boolean_t
        !          2443: socket_multicast_enable(
        !          2444:        endpt *         iface,
        !          2445:        sockaddr_u *    maddr
        !          2446:        )
        !          2447: {
        !          2448:        struct ip_mreq          mreq;
        !          2449: #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
        !          2450:        struct ipv6_mreq        mreq6;
        !          2451: #endif
        !          2452:        switch (AF(maddr)) {
        !          2453: 
        !          2454:        case AF_INET:
        !          2455:                memset(&mreq, 0, sizeof(mreq));
        !          2456:                mreq.imr_multiaddr = SOCK_ADDR4(maddr);
        !          2457:                mreq.imr_interface.s_addr = htonl(INADDR_ANY);
        !          2458:                if (setsockopt(iface->fd,
        !          2459:                               IPPROTO_IP,
        !          2460:                               IP_ADD_MEMBERSHIP,
        !          2461:                               (char *)&mreq, 
        !          2462:                               sizeof(mreq))) {
        !          2463:                        msyslog(LOG_ERR,
        !          2464:                                "setsockopt IP_ADD_MEMBERSHIP failed: %m on socket %d, addr %s for %x / %x (%s)",
        !          2465:                                iface->fd, stoa(&iface->sin),
        !          2466:                                mreq.imr_multiaddr.s_addr,
        !          2467:                                mreq.imr_interface.s_addr,
        !          2468:                                stoa(maddr));
        !          2469:                        return ISC_FALSE;
        !          2470:                }
        !          2471:                DPRINTF(4, ("Added IPv4 multicast membership on socket %d, addr %s for %x / %x (%s)\n",
        !          2472:                            iface->fd, stoa(&iface->sin),
        !          2473:                            mreq.imr_multiaddr.s_addr,
        !          2474:                            mreq.imr_interface.s_addr, stoa(maddr)));
        !          2475:                break;
        !          2476: 
        !          2477:        case AF_INET6:
        !          2478: #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
        !          2479:                /*
        !          2480:                 * Enable reception of multicast packets.
        !          2481:                 * If the address is link-local we can get the
        !          2482:                 * interface index from the scope id. Don't do this
        !          2483:                 * for other types of multicast addresses. For now let
        !          2484:                 * the kernel figure it out.
        !          2485:                 */
        !          2486:                memset(&mreq6, 0, sizeof(mreq6));
        !          2487:                mreq6.ipv6mr_multiaddr = SOCK_ADDR6(maddr);
        !          2488:                mreq6.ipv6mr_interface = iface->ifindex;
        !          2489: 
        !          2490:                if (setsockopt(iface->fd, IPPROTO_IPV6,
        !          2491:                               IPV6_JOIN_GROUP, (char *)&mreq6, 
        !          2492:                               sizeof(mreq6))) {
        !          2493:                        msyslog(LOG_ERR,
        !          2494:                                "setsockopt IPV6_JOIN_GROUP failed: %m on socket %d, addr %s for interface %u (%s)",
        !          2495:                                iface->fd, stoa(&iface->sin),
        !          2496:                                mreq6.ipv6mr_interface, stoa(maddr));
        !          2497:                        return ISC_FALSE;
        !          2498:                }
        !          2499:                DPRINTF(4, ("Added IPv6 multicast group on socket %d, addr %s for interface %u (%s)\n",
        !          2500:                            iface->fd, stoa(&iface->sin),
        !          2501:                            mreq6.ipv6mr_interface, stoa(maddr)));
        !          2502: #else
        !          2503:                return ISC_FALSE;
        !          2504: #endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */
        !          2505:        }
        !          2506:        iface->flags |= INT_MCASTOPEN;
        !          2507:        iface->num_mcast++;
        !          2508: 
        !          2509:        return ISC_TRUE;
        !          2510: }
        !          2511: #endif /* MCAST */
        !          2512: 
        !          2513: 
        !          2514: /*
        !          2515:  * Remove a multicast address from a given socket
        !          2516:  * The socket is in the inter_list all we need to do is disable
        !          2517:  * multicasting. It is not this function's job to select the socket
        !          2518:  */
        !          2519: #ifdef MCAST
        !          2520: static isc_boolean_t
        !          2521: socket_multicast_disable(
        !          2522:        struct interface *      iface,
        !          2523:        sockaddr_u *            maddr
        !          2524:        )
        !          2525: {
        !          2526: #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
        !          2527:        struct ipv6_mreq mreq6;
        !          2528: #endif
        !          2529:        struct ip_mreq mreq;
        !          2530: 
        !          2531:        memset(&mreq, 0, sizeof(mreq));
        !          2532: 
        !          2533:        if (find_addr_in_list(maddr) == NULL) {
        !          2534:                DPRINTF(4, ("socket_multicast_disable(%s): not found\n", 
        !          2535:                            stoa(maddr)));
        !          2536:                return ISC_TRUE;
        !          2537:        }
        !          2538: 
        !          2539:        switch (AF(maddr)) {
        !          2540: 
        !          2541:        case AF_INET:
        !          2542:                mreq.imr_multiaddr = SOCK_ADDR4(maddr);
        !          2543:                mreq.imr_interface = SOCK_ADDR4(&iface->sin);
        !          2544:                if (setsockopt(iface->fd, IPPROTO_IP,
        !          2545:                               IP_DROP_MEMBERSHIP, (char *)&mreq,
        !          2546:                               sizeof(mreq))) {
        !          2547: 
        !          2548:                        msyslog(LOG_ERR,
        !          2549:                                "setsockopt IP_DROP_MEMBERSHIP failed: %m on socket %d, addr %s for %x / %x (%s)",
        !          2550:                                iface->fd, stoa(&iface->sin),
        !          2551:                                SRCADR(maddr), SRCADR(&iface->sin),
        !          2552:                                stoa(maddr));
        !          2553:                        return ISC_FALSE;
        !          2554:                }
        !          2555:                break;
        !          2556:        case AF_INET6:
        !          2557: #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
        !          2558:                /*
        !          2559:                 * Disable reception of multicast packets
        !          2560:                 * If the address is link-local we can get the
        !          2561:                 * interface index from the scope id.  Don't do this
        !          2562:                 * for other types of multicast addresses. For now let
        !          2563:                 * the kernel figure it out.
        !          2564:                 */
        !          2565:                mreq6.ipv6mr_multiaddr = SOCK_ADDR6(maddr);
        !          2566:                mreq6.ipv6mr_interface = iface->ifindex;
        !          2567: 
        !          2568:                if (setsockopt(iface->fd, IPPROTO_IPV6,
        !          2569:                               IPV6_LEAVE_GROUP, (char *)&mreq6,
        !          2570:                               sizeof(mreq6))) {
        !          2571: 
        !          2572:                        msyslog(LOG_ERR,
        !          2573:                                "setsockopt IPV6_LEAVE_GROUP failure: %m on socket %d, addr %s for %d (%s)",
        !          2574:                                iface->fd, stoa(&iface->sin),
        !          2575:                                iface->ifindex, stoa(maddr));
        !          2576:                        return ISC_FALSE;
        !          2577:                }
        !          2578:                break;
        !          2579: #else
        !          2580:                return ISC_FALSE;
        !          2581: #endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */
        !          2582:        }
        !          2583: 
        !          2584:        iface->num_mcast--;
        !          2585:        if (!iface->num_mcast)
        !          2586:                iface->flags &= ~INT_MCASTOPEN;
        !          2587: 
        !          2588:        return ISC_TRUE;
        !          2589: }
        !          2590: #endif /* MCAST */
        !          2591: 
        !          2592: /*
        !          2593:  * io_setbclient - open the broadcast client sockets
        !          2594:  */
        !          2595: void
        !          2596: io_setbclient(void)
        !          2597: {
        !          2598: #ifdef OPEN_BCAST_SOCKET 
        !          2599:        struct interface *      interf;
        !          2600:        int                     nif;
        !          2601:        isc_boolean_t           jstatus; 
        !          2602:        SOCKET                  fd;
        !          2603: 
        !          2604:        nif = 0;
        !          2605:        set_reuseaddr(1);
        !          2606: 
        !          2607:        for (interf = ep_list;
        !          2608:             interf != NULL;
        !          2609:             interf = interf->elink) {
        !          2610: 
        !          2611:                if (interf->flags & (INT_WILDCARD | INT_LOOPBACK))
        !          2612:                        continue;
        !          2613:          
        !          2614:                /* use only allowed addresses */
        !          2615:                if (interf->ignore_packets)
        !          2616:                        continue;
        !          2617: 
        !          2618: 
        !          2619:                /* Need a broadcast-capable interface */
        !          2620:                if (!(interf->flags & INT_BROADCAST))
        !          2621:                        continue;
        !          2622: 
        !          2623:                /* Only IPv4 addresses are valid for broadcast */
        !          2624:                NTP_REQUIRE(IS_IPV4(&interf->sin));
        !          2625: 
        !          2626:                /* Do we already have the broadcast address open? */
        !          2627:                if (interf->flags & INT_BCASTOPEN) {
        !          2628:                        /* 
        !          2629:                         * account for already open interfaces to avoid
        !          2630:                         * misleading warning below 
        !          2631:                         */
        !          2632:                        nif++;
        !          2633:                        continue;
        !          2634:                }
        !          2635: 
        !          2636:                /*
        !          2637:                 * Try to open the broadcast address
        !          2638:                 */
        !          2639:                interf->family = AF_INET;
        !          2640:                interf->bfd = open_socket(&interf->bcast, 1, 0, interf);
        !          2641: 
        !          2642:                /*
        !          2643:                 * If we succeeded then we use it otherwise enable
        !          2644:                 * broadcast on the interface address
        !          2645:                 */
        !          2646:                if (interf->bfd != INVALID_SOCKET) {
        !          2647:                        fd = interf->bfd;
        !          2648:                        jstatus = ISC_TRUE;
        !          2649:                } else {
        !          2650:                        fd = interf->fd;
        !          2651:                        jstatus = socket_broadcast_enable(interf, fd,
        !          2652:                                        &interf->sin);
        !          2653:                }
        !          2654: 
        !          2655:                /* Enable Broadcast on socket */
        !          2656:                if (jstatus) {
        !          2657:                        nif++;
        !          2658:                        msyslog(LOG_INFO,
        !          2659:                                "io_setbclient: Opened broadcast client on interface #%d %s",
        !          2660:                                interf->ifnum, interf->name);
        !          2661:                        interf->addr_refid = addr2refid(&interf->sin);
        !          2662:                }
        !          2663:        }
        !          2664:        set_reuseaddr(0);
        !          2665:        if (nif > 0)
        !          2666:                DPRINTF(1, ("io_setbclient: Opened broadcast clients\n"));
        !          2667:        else if (!nif)
        !          2668:                msyslog(LOG_ERR,
        !          2669:                        "Unable to listen for broadcasts, no broadcast interfaces available");
        !          2670: #else
        !          2671:        msyslog(LOG_ERR,
        !          2672:                "io_setbclient: Broadcast Client disabled by build");
        !          2673: #endif /* OPEN_BCAST_SOCKET */
        !          2674: }
        !          2675: 
        !          2676: /*
        !          2677:  * io_unsetbclient - close the broadcast client sockets
        !          2678:  */
        !          2679: void
        !          2680: io_unsetbclient(void)
        !          2681: {
        !          2682:        endpt *ep;
        !          2683: 
        !          2684:        for (ep = ep_list; ep != NULL; ep = ep->elink) {
        !          2685:                if (INT_WILDCARD & ep->flags)
        !          2686:                        continue;
        !          2687:                if (!(INT_BCASTOPEN & ep->flags))
        !          2688:                        continue;
        !          2689:                socket_broadcast_disable(ep, &ep->sin);
        !          2690:        }
        !          2691: }
        !          2692: 
        !          2693: /*
        !          2694:  * io_multicast_add() - add multicast group address
        !          2695:  */
        !          2696: void
        !          2697: io_multicast_add(
        !          2698:        sockaddr_u *addr
        !          2699:        )
        !          2700: {
        !          2701: #ifdef MCAST
        !          2702:        endpt * ep;
        !          2703:        endpt * one_ep;
        !          2704: 
        !          2705:        /*
        !          2706:         * Check to see if this is a multicast address
        !          2707:         */
        !          2708:        if (!addr_ismulticast(addr))
        !          2709:                return;
        !          2710: 
        !          2711:        /* If we already have it we can just return */
        !          2712:        if (NULL != find_flagged_addr_in_list(addr, INT_MCASTOPEN)) {
        !          2713:                msyslog(LOG_INFO, 
        !          2714:                        "Duplicate request found for multicast address %s",
        !          2715:                        stoa(addr));
        !          2716:                return;
        !          2717:        }
        !          2718: 
        !          2719: #ifndef MULTICAST_NONEWSOCKET
        !          2720:        ep = new_interface(NULL);
        !          2721:        
        !          2722:        /*
        !          2723:         * Open a new socket for the multicast address
        !          2724:         */
        !          2725:        ep->sin = *addr;
        !          2726:        SET_PORT(&ep->sin, NTP_PORT);
        !          2727:        ep->family = AF(&ep->sin);
        !          2728:        AF(&ep->mask) = ep->family;
        !          2729:        SET_ONESMASK(&ep->mask);
        !          2730: 
        !          2731:        set_reuseaddr(1);
        !          2732:        ep->bfd = INVALID_SOCKET;
        !          2733:        ep->fd = open_socket(&ep->sin, 0, 0, ep);
        !          2734:        if (ep->fd != INVALID_SOCKET) {
        !          2735:                ep->ignore_packets = ISC_FALSE;
        !          2736:                ep->flags |= INT_MCASTIF;
        !          2737:                
        !          2738:                strncpy(ep->name, "multicast", sizeof(ep->name));
        !          2739:                DPRINT_INTERFACE(2, (ep, "multicast add ", "\n"));
        !          2740:                add_interface(ep);
        !          2741:                log_listen_address(ep);
        !          2742:        } else {
        !          2743:                /* bind failed, re-use wildcard interface */
        !          2744:                delete_interface(ep);
        !          2745: 
        !          2746:                if (IS_IPV4(addr))
        !          2747:                        ep = wildipv4;
        !          2748:                else if (IS_IPV6(addr))
        !          2749:                        ep = wildipv6;
        !          2750:                else
        !          2751:                        ep = NULL;
        !          2752: 
        !          2753:                if (ep != NULL) {
        !          2754:                        /* HACK ! -- stuff in an address */
        !          2755:                        /* because we don't bind addr? DH */
        !          2756:                        ep->bcast = *addr;
        !          2757:                        msyslog(LOG_ERR,
        !          2758:                                "multicast address %s using wildcard interface #%d %s",
        !          2759:                                stoa(addr), ep->ifnum, ep->name);
        !          2760:                } else {
        !          2761:                        msyslog(LOG_ERR,
        !          2762:                                "No multicast socket available to use for address %s",
        !          2763:                                stoa(addr));
        !          2764:                        return;
        !          2765:                }
        !          2766:        }
        !          2767:        {       /* in place of the { following for in #else clause */
        !          2768:                one_ep = ep;
        !          2769: #else  /* MULTICAST_NONEWSOCKET follows */
        !          2770:        /*
        !          2771:         * For the case where we can't use a separate socket (Windows)
        !          2772:         * join each applicable endpoint socket to the group address.
        !          2773:         */
        !          2774:        if (IS_IPV4(addr))
        !          2775:                one_ep = wildipv4;
        !          2776:        else
        !          2777:                one_ep = wildipv6;
        !          2778:        for (ep = ep_list; ep != NULL; ep = ep->elink) {
        !          2779:                if (ep->ignore_packets || AF(&ep->sin) != AF(addr) ||
        !          2780:                    !(INT_MULTICAST & ep->flags) ||
        !          2781:                    (INT_LOOPBACK | INT_WILDCARD) & ep->flags)
        !          2782:                        continue;
        !          2783:                one_ep = ep;
        !          2784: #endif /* MULTICAST_NONEWSOCKET */
        !          2785:                if (socket_multicast_enable(ep, addr))
        !          2786:                        msyslog(LOG_INFO, 
        !          2787:                                "Joined %s socket to multicast group %s",
        !          2788:                                stoa(&ep->sin),
        !          2789:                                stoa(addr));
        !          2790:                else
        !          2791:                        msyslog(LOG_ERR,
        !          2792:                                "Failed to join %s socket to multicast group %s",
        !          2793:                                stoa(&ep->sin),
        !          2794:                                stoa(addr));
        !          2795:        }
        !          2796: 
        !          2797:        add_addr_to_list(addr, one_ep);
        !          2798: #else  /* !MCAST  follows*/
        !          2799:        msyslog(LOG_ERR,
        !          2800:                "Can not add multicast address %s: no multicast support",
        !          2801:                stoa(addr));
        !          2802: #endif
        !          2803:        return;
        !          2804: }
        !          2805: 
        !          2806: 
        !          2807: /*
        !          2808:  * io_multicast_del() - delete multicast group address
        !          2809:  */
        !          2810: void
        !          2811: io_multicast_del(
        !          2812:        sockaddr_u *    addr
        !          2813:        )
        !          2814: {
        !          2815: #ifdef MCAST
        !          2816:        endpt *iface;
        !          2817: 
        !          2818:        /*
        !          2819:         * Check to see if this is a multicast address
        !          2820:         */
        !          2821:        if (!addr_ismulticast(addr)) {
        !          2822:                msyslog(LOG_ERR, "invalid multicast address %s",
        !          2823:                        stoa(addr));
        !          2824:                return;
        !          2825:        }
        !          2826: 
        !          2827:        /*
        !          2828:         * Disable reception of multicast packets
        !          2829:         */
        !          2830:        while ((iface = find_flagged_addr_in_list(addr, INT_MCASTOPEN))
        !          2831:               != NULL)
        !          2832:                socket_multicast_disable(iface, addr);
        !          2833: 
        !          2834:        delete_addr_from_list(addr);
        !          2835: 
        !          2836: #else /* not MCAST */
        !          2837:        msyslog(LOG_ERR,
        !          2838:                "Can not delete multicast address %s: no multicast support",
        !          2839:                stoa(addr));
        !          2840: #endif /* not MCAST */
        !          2841: }
        !          2842: 
        !          2843: 
        !          2844: /*
        !          2845:  * init_nonblocking_io() - set up descriptor to be non blocking
        !          2846:  */
        !          2847: static void init_nonblocking_io(
        !          2848:        SOCKET fd
        !          2849:        )
        !          2850: {
        !          2851:        /*
        !          2852:         * set non-blocking,
        !          2853:         */
        !          2854: 
        !          2855: #ifdef USE_FIONBIO
        !          2856:        /* in vxWorks we use FIONBIO, but the others are defined for old systems, so
        !          2857:         * all hell breaks loose if we leave them defined
        !          2858:         */
        !          2859: #undef O_NONBLOCK
        !          2860: #undef FNDELAY
        !          2861: #undef O_NDELAY
        !          2862: #endif
        !          2863: 
        !          2864: #if defined(O_NONBLOCK) /* POSIX */
        !          2865:        if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
        !          2866:                msyslog(LOG_ERR,
        !          2867:                        "fcntl(O_NONBLOCK) fails on fd #%d: %m", fd);
        !          2868:                exit(1);
        !          2869:        }
        !          2870: #elif defined(FNDELAY)
        !          2871:        if (fcntl(fd, F_SETFL, FNDELAY) < 0) {
        !          2872:                msyslog(LOG_ERR, "fcntl(FNDELAY) fails on fd #%d: %m",
        !          2873:                        fd);
        !          2874:                exit(1);
        !          2875:        }
        !          2876: #elif defined(O_NDELAY) /* generally the same as FNDELAY */
        !          2877:        if (fcntl(fd, F_SETFL, O_NDELAY) < 0) {
        !          2878:                msyslog(LOG_ERR, "fcntl(O_NDELAY) fails on fd #%d: %m",
        !          2879:                        fd);
        !          2880:                exit(1);
        !          2881:        }
        !          2882: #elif defined(FIONBIO)
        !          2883:        {
        !          2884:                int on = 1;
        !          2885: 
        !          2886:                if (ioctl(fd, FIONBIO, &on) < 0) {
        !          2887:                        msyslog(LOG_ERR,
        !          2888:                                "ioctl(FIONBIO) fails on fd #%d: %m",
        !          2889:                                fd);
        !          2890:                        exit(1);
        !          2891:                }
        !          2892:        }
        !          2893: #elif defined(FIOSNBIO)
        !          2894:        if (ioctl(fd, FIOSNBIO, &on) < 0) {
        !          2895:                msyslog(LOG_ERR,
        !          2896:                        "ioctl(FIOSNBIO) fails on fd #%d: %m", fd);
        !          2897:                exit(1);
        !          2898:        }
        !          2899: #else
        !          2900: # include "Bletch: Need non-blocking I/O!"
        !          2901: #endif
        !          2902: }
        !          2903: 
        !          2904: /*
        !          2905:  * open_socket - open a socket, returning the file descriptor
        !          2906:  */
        !          2907: 
        !          2908: static SOCKET
        !          2909: open_socket(
        !          2910:        sockaddr_u *    addr,
        !          2911:        int             bcast,
        !          2912:        int             turn_off_reuse,
        !          2913:        endpt *         interf
        !          2914:        )
        !          2915: {
        !          2916:        SOCKET  fd;
        !          2917:        int     errval;
        !          2918:        char    scopetext[16];
        !          2919:        /*
        !          2920:         * int is OK for REUSEADR per 
        !          2921:         * http://www.kohala.com/start/mcast.api.txt
        !          2922:         */
        !          2923:        int     on = 1;
        !          2924:        int     off = 0;
        !          2925: 
        !          2926:        if (IS_IPV6(addr) && !ipv6_works)
        !          2927:                return INVALID_SOCKET;
        !          2928: 
        !          2929:        /* create a datagram (UDP) socket */
        !          2930:        fd = socket(AF(addr), SOCK_DGRAM, 0);
        !          2931:        if (INVALID_SOCKET == fd) {
        !          2932:                errval = socket_errno();
        !          2933:                msyslog(LOG_ERR, 
        !          2934:                        "socket(AF_INET%s, SOCK_DGRAM, 0) failed on address %s: %m",
        !          2935:                        IS_IPV6(addr) ? "6" : "", stoa(addr));
        !          2936: 
        !          2937:                if (errval == EPROTONOSUPPORT || 
        !          2938:                    errval == EAFNOSUPPORT ||
        !          2939:                    errval == EPFNOSUPPORT)
        !          2940:                        return (INVALID_SOCKET);
        !          2941: 
        !          2942:                errno = errval;
        !          2943:                msyslog(LOG_ERR,
        !          2944:                        "unexpected socket() error %m code %d (not EPROTONOSUPPORT nor EAFNOSUPPORT nor EPFNOSUPPORT) - exiting",
        !          2945:                        errno);
        !          2946:                exit(1);
        !          2947:        }
        !          2948: 
        !          2949: #ifdef SYS_WINNT
        !          2950:        connection_reset_fix(fd, addr);
        !          2951: #endif
        !          2952:        /*
        !          2953:         * Fixup the file descriptor for some systems
        !          2954:         * See bug #530 for details of the issue.
        !          2955:         */
        !          2956:        fd = move_fd(fd);
        !          2957: 
        !          2958:        /*
        !          2959:         * set SO_REUSEADDR since we will be binding the same port
        !          2960:         * number on each interface according to turn_off_reuse.
        !          2961:         * This is undesirable on Windows versions starting with
        !          2962:         * Windows XP (numeric version 5.1).
        !          2963:         */
        !          2964: #ifdef SYS_WINNT
        !          2965:        if (isc_win32os_versioncheck(5, 1, 0, 0) < 0)  /* before 5.1 */
        !          2966: #endif
        !          2967:                if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
        !          2968:                               (char *)((turn_off_reuse) 
        !          2969:                                            ? &off 
        !          2970:                                            : &on), 
        !          2971:                               sizeof(on))) {
        !          2972: 
        !          2973:                        msyslog(LOG_ERR,
        !          2974:                                "setsockopt SO_REUSEADDR %s fails for address %s: %m",
        !          2975:                                (turn_off_reuse)
        !          2976:                                    ? "off" 
        !          2977:                                    : "on", 
        !          2978:                                stoa(addr));
        !          2979:                        closesocket(fd);
        !          2980:                        return INVALID_SOCKET;
        !          2981:                }
        !          2982: #ifdef SO_EXCLUSIVEADDRUSE
        !          2983:        /*
        !          2984:         * setting SO_EXCLUSIVEADDRUSE on the wildcard we open
        !          2985:         * first will cause more specific binds to fail.
        !          2986:         */
        !          2987:        if (!(interf->flags & INT_WILDCARD))
        !          2988:                set_excladdruse(fd);
        !          2989: #endif
        !          2990: 
        !          2991:        /*
        !          2992:         * IPv4 specific options go here
        !          2993:         */
        !          2994:        if (IS_IPV4(addr)) {
        !          2995: #if defined(HAVE_IPTOS_SUPPORT)
        !          2996:                if (setsockopt(fd, IPPROTO_IP, IP_TOS, (char *)&qos,
        !          2997:                               sizeof(qos)))
        !          2998:                        msyslog(LOG_ERR,
        !          2999:                                "setsockopt IP_TOS (%02x) fails on address %s: %m",
        !          3000:                                qos, stoa(addr));
        !          3001: #endif /* HAVE_IPTOS_SUPPORT */
        !          3002:                if (bcast)
        !          3003:                        socket_broadcast_enable(interf, fd, addr);
        !          3004:        }
        !          3005: 
        !          3006:        /*
        !          3007:         * IPv6 specific options go here
        !          3008:         */
        !          3009:        if (IS_IPV6(addr)) {
        !          3010: #ifdef IPV6_V6ONLY
        !          3011:                if (isc_net_probe_ipv6only() == ISC_R_SUCCESS
        !          3012:                    && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
        !          3013:                    (char*)&on, sizeof(on)))
        !          3014:                        msyslog(LOG_ERR,
        !          3015:                                "setsockopt IPV6_V6ONLY on fails on address %s: %m",
        !          3016:                                stoa(addr));
        !          3017: #endif
        !          3018: #ifdef IPV6_BINDV6ONLY
        !          3019:                if (setsockopt(fd, IPPROTO_IPV6, IPV6_BINDV6ONLY,
        !          3020:                    (char*)&on, sizeof(on)))
        !          3021:                        msyslog(LOG_ERR,
        !          3022:                                "setsockopt IPV6_BINDV6ONLY on fails on address %s: %m",
        !          3023:                                stoa(addr));
        !          3024: #endif
        !          3025:        }
        !          3026: 
        !          3027: #ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND
        !          3028:        /*
        !          3029:         * some OSes don't allow binding to more specific
        !          3030:         * addresses if a wildcard address already bound
        !          3031:         * to the port and SO_REUSEADDR is not set
        !          3032:         */
        !          3033:        if (!is_wildcard_addr(addr))
        !          3034:                set_wildcard_reuse(AF(addr), 1);
        !          3035: #endif
        !          3036: 
        !          3037:        /*
        !          3038:         * bind the local address.
        !          3039:         */
        !          3040:        errval = bind(fd, &addr->sa, SOCKLEN(addr));
        !          3041: 
        !          3042: #ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND
        !          3043:        if (!is_wildcard_addr(addr))
        !          3044:                set_wildcard_reuse(AF(addr), 0);
        !          3045: #endif
        !          3046: 
        !          3047:        if (errval < 0) {
        !          3048:                /*
        !          3049:                 * Don't log this under all conditions
        !          3050:                 */
        !          3051:                if (turn_off_reuse == 0
        !          3052: #ifdef DEBUG
        !          3053:                    || debug > 1
        !          3054: #endif
        !          3055:                    ) {
        !          3056:                        if (SCOPE(addr))
        !          3057:                                snprintf(scopetext, sizeof(scopetext),
        !          3058:                                         "%%%d", SCOPE(addr));
        !          3059:                        else
        !          3060:                                scopetext[0] = 0;
        !          3061: 
        !          3062:                        msyslog(LOG_ERR,
        !          3063:                                "bind(%d) AF_INET%s %s%s#%d%s flags 0x%x failed: %m",
        !          3064:                                fd, IS_IPV6(addr) ? "6" : "",
        !          3065:                                stoa(addr), scopetext, SRCPORT(addr),
        !          3066:                                IS_MCAST(addr) ? " (multicast)" : "",
        !          3067:                                interf->flags);
        !          3068:                }
        !          3069: 
        !          3070:                closesocket(fd);
        !          3071:                
        !          3072:                return INVALID_SOCKET;
        !          3073:        }
        !          3074: 
        !          3075: #ifdef HAVE_TIMESTAMP
        !          3076:        {
        !          3077:                if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP,
        !          3078:                               (char*)&on, sizeof(on)))
        !          3079:                        msyslog(LOG_DEBUG,
        !          3080:                                "setsockopt SO_TIMESTAMP on fails on address %s: %m",
        !          3081:                                stoa(addr));
        !          3082:                else
        !          3083:                        DPRINTF(4, ("setsockopt SO_TIMESTAMP enabled on fd %d address %s\n",
        !          3084:                                    fd, stoa(addr)));
        !          3085:        }       
        !          3086: #endif
        !          3087:        DPRINTF(4, ("bind(%d) AF_INET%s, addr %s%%%d#%d, flags 0x%x\n",
        !          3088:                   fd, IS_IPV6(addr) ? "6" : "", stoa(addr),
        !          3089:                   SCOPE(addr), SRCPORT(addr), interf->flags));
        !          3090: 
        !          3091:        init_nonblocking_io(fd);
        !          3092:        
        !          3093: #ifdef HAVE_SIGNALED_IO
        !          3094:        init_socket_sig(fd);
        !          3095: #endif /* not HAVE_SIGNALED_IO */
        !          3096: 
        !          3097:        add_fd_to_list(fd, FD_TYPE_SOCKET);
        !          3098: 
        !          3099: #if !defined(SYS_WINNT) && !defined(VMS)
        !          3100:        DPRINTF(4, ("flags for fd %d: 0x%x\n", fd,
        !          3101:                    fcntl(fd, F_GETFL, 0)));
        !          3102: #endif /* SYS_WINNT || VMS */
        !          3103: 
        !          3104: #if defined (HAVE_IO_COMPLETION_PORT)
        !          3105: /*
        !          3106:  * Add the socket to the completion port
        !          3107:  */
        !          3108:        if (io_completion_port_add_socket(fd, interf)) {
        !          3109:                msyslog(LOG_ERR, "unable to set up io completion port - EXITING");
        !          3110:                exit(1);
        !          3111:        }
        !          3112: #endif
        !          3113:        return fd;
        !          3114: }
        !          3115: 
        !          3116: 
        !          3117: #ifdef SYS_WINNT
        !          3118: #define sendto(fd, buf, len, flags, dest, destsz)      \
        !          3119:        io_completion_port_sendto(fd, buf, len, (sockaddr_u *)(dest))
        !          3120: #endif
        !          3121: 
        !          3122: /* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
        !          3123: /*
        !          3124:  * sendpkt - send a packet to the specified destination. Maintain a
        !          3125:  * send error cache so that only the first consecutive error for a
        !          3126:  * destination is logged.
        !          3127:  */
        !          3128: void
        !          3129: sendpkt(
        !          3130:        sockaddr_u *            dest,
        !          3131:        struct interface *      ep,
        !          3132:        int                     ttl,
        !          3133:        struct pkt *            pkt,
        !          3134:        int                     len
        !          3135:        )
        !          3136: {
        !          3137:        endpt * src;
        !          3138:        int     ismcast;
        !          3139:        int     cc;
        !          3140:        int     rc;
        !          3141:        u_char  cttl;
        !          3142: 
        !          3143:        ismcast = IS_MCAST(dest);
        !          3144:        if (!ismcast)
        !          3145:                src = ep;
        !          3146:        else
        !          3147:                src = (IS_IPV4(dest))
        !          3148:                          ? mc4_list
        !          3149:                          : mc6_list;
        !          3150:        
        !          3151:        if (NULL == src) {
        !          3152:                /*
        !          3153:                 * unbound peer - drop request and wait for better
        !          3154:                 * network conditions 
        !          3155:                 */
        !          3156:                DPRINTF(2, ("%ssendpkt(dst=%s, ttl=%d, len=%d): no interface - IGNORED\n",
        !          3157:                            ismcast ? "\tMCAST\t***** " : "",
        !          3158:                            stoa(dest), ttl, len));
        !          3159:                return;
        !          3160:        }
        !          3161: 
        !          3162:        do {
        !          3163:                DPRINTF(2, ("%ssendpkt(%d, dst=%s, src=%s, ttl=%d, len=%d)\n",
        !          3164:                            ismcast ? "\tMCAST\t***** " : "", src->fd,
        !          3165:                            stoa(dest), stoa(&src->sin), ttl, len));
        !          3166: #ifdef MCAST
        !          3167:                /*
        !          3168:                 * for the moment we use the bcast option to set multicast ttl
        !          3169:                 */
        !          3170:                if (ismcast && ttl > 0 && ttl != src->last_ttl) {
        !          3171:                        /*
        !          3172:                         * set the multicast ttl for outgoing packets
        !          3173:                         */
        !          3174:                        switch (AF(&src->sin)) {
        !          3175:                                
        !          3176:                        case AF_INET :
        !          3177:                                cttl = (u_char)ttl;
        !          3178:                                rc = setsockopt(src->fd, IPPROTO_IP,
        !          3179:                                                IP_MULTICAST_TTL,
        !          3180:                                                (void *)&cttl,
        !          3181:                                                sizeof(cttl));
        !          3182:                                break;
        !          3183:                                
        !          3184: # ifdef INCLUDE_IPV6_SUPPORT
        !          3185:                        case AF_INET6 :
        !          3186:                                rc = setsockopt(src->fd, IPPROTO_IPV6,
        !          3187:                                                 IPV6_MULTICAST_HOPS,
        !          3188:                                                 (void *)&ttl,
        !          3189:                                                 sizeof(ttl));
        !          3190:                                break;
        !          3191: # endif        /* INCLUDE_IPV6_SUPPORT */
        !          3192: 
        !          3193:                        default:
        !          3194:                                rc = 0;
        !          3195:                        }
        !          3196:                        
        !          3197:                        if (!rc)
        !          3198:                                src->last_ttl = ttl;
        !          3199:                        else
        !          3200:                                msyslog(LOG_ERR, 
        !          3201:                                        "setsockopt IP_MULTICAST_TTL/IPV6_MULTICAST_HOPS fails on address %s: %m",
        !          3202:                                        stoa(&src->sin));
        !          3203:                }
        !          3204: #endif /* MCAST */
        !          3205: 
        !          3206: #ifdef SIM
        !          3207:                cc = simulate_server(dest, src, pkt);
        !          3208: #else
        !          3209:                cc = sendto(src->fd, (char *)pkt, (u_int)len, 0,
        !          3210:                            &dest->sa, SOCKLEN(dest));
        !          3211: #endif
        !          3212:                if (cc == -1) {
        !          3213:                        src->notsent++;
        !          3214:                        packets_notsent++;
        !          3215:                } else  {
        !          3216:                        src->sent++;
        !          3217:                        packets_sent++;
        !          3218:                }
        !          3219:                if (ismcast)
        !          3220:                        src = src->mclink;
        !          3221:        } while (ismcast && src != NULL);
        !          3222: }
        !          3223: 
        !          3224: 
        !          3225: #if !defined(HAVE_IO_COMPLETION_PORT)
        !          3226: /*
        !          3227:  * fdbits - generate ascii representation of fd_set (FAU debug support)
        !          3228:  * HFDF format - highest fd first.
        !          3229:  */
        !          3230: static char *
        !          3231: fdbits(
        !          3232:        int count,
        !          3233:        fd_set *set
        !          3234:        )
        !          3235: {
        !          3236:        static char buffer[256];
        !          3237:        char * buf = buffer;
        !          3238: 
        !          3239:        count = min(count,  255);
        !          3240: 
        !          3241:        while (count >= 0) {
        !          3242:                *buf++ = FD_ISSET(count, set) ? '#' : '-';
        !          3243:                count--;
        !          3244:        }
        !          3245:        *buf = '\0';
        !          3246: 
        !          3247:        return buffer;
        !          3248: }
        !          3249: 
        !          3250: /*
        !          3251:  * Routine to read the refclock packets for a specific interface
        !          3252:  * Return the number of bytes read. That way we know if we should
        !          3253:  * read it again or go on to the next one if no bytes returned
        !          3254:  */
        !          3255: static inline int
        !          3256: read_refclock_packet(SOCKET fd, struct refclockio *rp, l_fp ts)
        !          3257: {
        !          3258:        int i;
        !          3259:        int buflen;
        !          3260:        register struct recvbuf *rb;
        !          3261: 
        !          3262:        rb = get_free_recv_buffer();
        !          3263: 
        !          3264:        if (NULL == rb) {
        !          3265:                /*
        !          3266:                 * No buffer space available - just drop the packet
        !          3267:                 */
        !          3268:                char buf[RX_BUFF_SIZE];
        !          3269: 
        !          3270:                buflen = read(fd, buf, sizeof buf);
        !          3271:                packets_dropped++;
        !          3272:                return (buflen);
        !          3273:        }
        !          3274: 
        !          3275:        i = (rp->datalen == 0
        !          3276:             || rp->datalen > sizeof(rb->recv_space))
        !          3277:                ? sizeof(rb->recv_space)
        !          3278:                : rp->datalen;
        !          3279:        buflen = read(fd, (char *)&rb->recv_space, (unsigned)i);
        !          3280: 
        !          3281:        if (buflen < 0) {
        !          3282:                if (errno != EINTR && errno != EAGAIN)
        !          3283:                        msyslog(LOG_ERR, "clock read fd %d: %m", fd);
        !          3284:                freerecvbuf(rb);
        !          3285:                return (buflen);
        !          3286:        }
        !          3287: 
        !          3288:        /*
        !          3289:         * Got one. Mark how and when it got here,
        !          3290:         * put it on the full list and do bookkeeping.
        !          3291:         */
        !          3292:        rb->recv_length = buflen;
        !          3293:        rb->recv_srcclock = rp->srcclock;
        !          3294:        rb->dstadr = 0;
        !          3295:        rb->fd = fd;
        !          3296:        rb->recv_time = ts;
        !          3297:        rb->receiver = rp->clock_recv;
        !          3298: 
        !          3299:        if (rp->io_input) {
        !          3300:                /*
        !          3301:                 * have direct input routine for refclocks
        !          3302:                 */
        !          3303:                if (rp->io_input(rb) == 0) {
        !          3304:                        /*
        !          3305:                         * data was consumed - nothing to pass up
        !          3306:                         * into block input machine
        !          3307:                         */
        !          3308:                        freerecvbuf(rb);
        !          3309:                        return (buflen);
        !          3310:                }
        !          3311:        }
        !          3312:        
        !          3313:        add_full_recv_buffer(rb);
        !          3314: 
        !          3315:        rp->recvcount++;
        !          3316:        packets_received++;
        !          3317:        return (buflen);
        !          3318: }
        !          3319: 
        !          3320: 
        !          3321: #ifdef HAVE_TIMESTAMP
        !          3322: /*
        !          3323:  * extract timestamps from control message buffer
        !          3324:  */
        !          3325: static l_fp
        !          3326: fetch_timestamp(
        !          3327:        struct recvbuf *        rb,
        !          3328:        struct msghdr *         msghdr, 
        !          3329:        l_fp                    ts
        !          3330:        )
        !          3331: {
        !          3332: #ifdef USE_TIMESTAMP_CMSG
        !          3333:        struct cmsghdr *cmsghdr;
        !          3334: 
        !          3335:        cmsghdr = CMSG_FIRSTHDR(msghdr);
        !          3336:        while (cmsghdr != NULL) {
        !          3337:                switch (cmsghdr->cmsg_type)
        !          3338:                {
        !          3339:                case SCM_TIMESTAMP:
        !          3340:                {
        !          3341:                        struct timeval *tvp;
        !          3342:                        double dtemp;
        !          3343:                        l_fp nts;
        !          3344: 
        !          3345:                        tvp = (struct timeval *)CMSG_DATA(cmsghdr);
        !          3346:                        DPRINTF(4, ("fetch_timestamp: system network time stamp: %ld.%06ld\n",
        !          3347:                                    tvp->tv_sec, tvp->tv_usec));
        !          3348:                        nts.l_i = tvp->tv_sec + JAN_1970;
        !          3349:                        dtemp = (tvp->tv_usec 
        !          3350:                                 + (ntp_random() * 2. / FRAC)) / 1e6;
        !          3351:                        nts.l_uf = (u_int32)(dtemp * FRAC);
        !          3352: #ifdef DEBUG_TIMING
        !          3353:                        {
        !          3354:                                l_fp dts;
        !          3355: 
        !          3356:                                dts = ts;
        !          3357:                                L_SUB(&dts, &nts);
        !          3358:                                collect_timing(rb, 
        !          3359:                                               "input processing delay",
        !          3360:                                               1, &dts);
        !          3361:                                DPRINTF(4, ("fetch_timestamp: timestamp delta: %s (incl. prec fuzz)\n",
        !          3362:                                            lfptoa(&dts, 9)));
        !          3363:                        }
        !          3364: #endif
        !          3365:                        ts = nts;  /* network time stamp */
        !          3366:                        break;
        !          3367:                }
        !          3368:                default:
        !          3369:                        DPRINTF(4, ("fetch_timestamp: skipping control message 0x%x\n",
        !          3370:                                    cmsghdr->cmsg_type));
        !          3371:                }
        !          3372:                cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr);
        !          3373:        }
        !          3374: #endif
        !          3375:        return ts;
        !          3376: }
        !          3377: #endif
        !          3378: 
        !          3379: 
        !          3380: /*
        !          3381:  * Routine to read the network NTP packets for a specific interface
        !          3382:  * Return the number of bytes read. That way we know if we should
        !          3383:  * read it again or go on to the next one if no bytes returned
        !          3384:  */
        !          3385: static inline int
        !          3386: read_network_packet(
        !          3387:        SOCKET                  fd,
        !          3388:        struct interface *      itf,
        !          3389:        l_fp                    ts
        !          3390:        )
        !          3391: {
        !          3392:        GETSOCKNAME_SOCKLEN_TYPE fromlen;
        !          3393:        int buflen;
        !          3394:        register struct recvbuf *rb;
        !          3395: #ifdef HAVE_TIMESTAMP
        !          3396:        struct msghdr msghdr;
        !          3397:        struct iovec iovec;
        !          3398:        char control[TIMESTAMP_CTLMSGBUF_SIZE];
        !          3399: #endif
        !          3400: 
        !          3401:        /*
        !          3402:         * Get a buffer and read the frame.  If we
        !          3403:         * haven't got a buffer, or this is received
        !          3404:         * on a disallowed socket, just dump the
        !          3405:         * packet.
        !          3406:         */
        !          3407: 
        !          3408:        rb = get_free_recv_buffer();
        !          3409:        if (NULL == rb || itf->ignore_packets) {
        !          3410:                char buf[RX_BUFF_SIZE];
        !          3411:                sockaddr_u from;
        !          3412: 
        !          3413:                if (rb != NULL)
        !          3414:                        freerecvbuf(rb);
        !          3415: 
        !          3416:                fromlen = sizeof(from);
        !          3417:                buflen = recvfrom(fd, buf, sizeof(buf), 0,
        !          3418:                                  &from.sa, &fromlen);
        !          3419:                DPRINTF(4, ("%s on (%lu) fd=%d from %s\n",
        !          3420:                        (itf->ignore_packets)
        !          3421:                            ? "ignore"
        !          3422:                            : "drop",
        !          3423:                        free_recvbuffs(), fd, stoa(&from)));
        !          3424:                if (itf->ignore_packets)
        !          3425:                        packets_ignored++;
        !          3426:                else
        !          3427:                        packets_dropped++;
        !          3428:                return (buflen);
        !          3429:        }
        !          3430: 
        !          3431:        fromlen = sizeof(rb->recv_srcadr);
        !          3432: 
        !          3433: #ifndef HAVE_TIMESTAMP
        !          3434:        rb->recv_length = recvfrom(fd, (char *)&rb->recv_space,
        !          3435:                                   sizeof(rb->recv_space), 0,
        !          3436:                                   &rb->recv_srcadr.sa, &fromlen);
        !          3437: #else
        !          3438:        iovec.iov_base        = &rb->recv_space;
        !          3439:        iovec.iov_len         = sizeof(rb->recv_space);
        !          3440:        msghdr.msg_name       = &rb->recv_srcadr;
        !          3441:        msghdr.msg_namelen    = fromlen;
        !          3442:        msghdr.msg_iov        = &iovec;
        !          3443:        msghdr.msg_iovlen     = 1;
        !          3444:        msghdr.msg_control    = (void *)&control;
        !          3445:        msghdr.msg_controllen = sizeof(control);
        !          3446:        msghdr.msg_flags      = 0;
        !          3447:        rb->recv_length       = recvmsg(fd, &msghdr, 0);
        !          3448: #endif
        !          3449: 
        !          3450:        buflen = rb->recv_length;
        !          3451: 
        !          3452:        if (buflen == 0 || (buflen == -1 && 
        !          3453:            (EWOULDBLOCK == errno
        !          3454: #ifdef EAGAIN
        !          3455:             || EAGAIN == errno
        !          3456: #endif
        !          3457:             ))) {
        !          3458:                freerecvbuf(rb);
        !          3459:                return (buflen);
        !          3460:        } else if (buflen < 0) {
        !          3461:                msyslog(LOG_ERR, "recvfrom(%s) fd=%d: %m",
        !          3462:                        stoa(&rb->recv_srcadr), fd);
        !          3463:                DPRINTF(5, ("read_network_packet: fd=%d dropped (bad recvfrom)\n",
        !          3464:                            fd));
        !          3465:                freerecvbuf(rb);
        !          3466:                return (buflen);
        !          3467:        }
        !          3468: 
        !          3469:        DPRINTF(3, ("read_network_packet: fd=%d length %d from %s\n",
        !          3470:                    fd, buflen, stoa(&rb->recv_srcadr)));
        !          3471: 
        !          3472:        /*
        !          3473:         * Got one.  Mark how and when it got here,
        !          3474:         * put it on the full list and do bookkeeping.
        !          3475:         */
        !          3476:        rb->dstadr = itf;
        !          3477:        rb->fd = fd;
        !          3478: #ifdef HAVE_TIMESTAMP
        !          3479:        /* pick up a network time stamp if possible */
        !          3480:        ts = fetch_timestamp(rb, &msghdr, ts);
        !          3481: #endif
        !          3482:        rb->recv_time = ts;
        !          3483:        rb->receiver = receive;
        !          3484: 
        !          3485:        add_full_recv_buffer(rb);
        !          3486: 
        !          3487:        itf->received++;
        !          3488:        packets_received++;
        !          3489:        return (buflen);
        !          3490: }
        !          3491: 
        !          3492: 
        !          3493: /*
        !          3494:  * input_handler - receive packets asynchronously
        !          3495:  */
        !          3496: void
        !          3497: input_handler(
        !          3498:        l_fp *cts
        !          3499:        )
        !          3500: {
        !          3501:        int buflen;
        !          3502:        int n;
        !          3503:        int doing;
        !          3504:        SOCKET fd;
        !          3505:        struct timeval tvzero;
        !          3506:        l_fp ts;                /* Timestamp at BOselect() gob */
        !          3507: #ifdef DEBUG_TIMING
        !          3508:        l_fp ts_e;              /* Timestamp at EOselect() gob */
        !          3509: #endif
        !          3510:        fd_set fds;
        !          3511:        int select_count = 0;
        !          3512:        endpt *ep;
        !          3513: #if defined(HAS_ROUTING_SOCKET)
        !          3514:        struct asyncio_reader *asyncio_reader;
        !          3515: #endif
        !          3516: 
        !          3517:        handler_calls++;
        !          3518: 
        !          3519:        /*
        !          3520:         * If we have something to do, freeze a timestamp.
        !          3521:         * See below for the other cases (nothing left to do or error)
        !          3522:         */
        !          3523:        ts = *cts;
        !          3524: 
        !          3525:        /*
        !          3526:         * Do a poll to see who has data
        !          3527:         */
        !          3528: 
        !          3529:        fds = activefds;
        !          3530:        tvzero.tv_sec = tvzero.tv_usec = 0;
        !          3531: 
        !          3532:        n = select(maxactivefd + 1, &fds, (fd_set *)0, (fd_set *)0,
        !          3533:                   &tvzero);
        !          3534: 
        !          3535:        /*
        !          3536:         * If there are no packets waiting just return
        !          3537:         */
        !          3538:        if (n < 0) {
        !          3539:                int err = errno;
        !          3540:                /*
        !          3541:                 * extended FAU debugging output
        !          3542:                 */
        !          3543:                if (err != EINTR)
        !          3544:                        msyslog(LOG_ERR,
        !          3545:                                "select(%d, %s, 0L, 0L, &0.0) error: %m",
        !          3546:                                maxactivefd + 1,
        !          3547:                                fdbits(maxactivefd, &activefds));
        !          3548:                if (err == EBADF) {
        !          3549:                        int j, b;
        !          3550:                        fds = activefds;
        !          3551:                        for (j = 0; j <= maxactivefd; j++)
        !          3552:                                if ((FD_ISSET(j, &fds)
        !          3553:                                    && (read(j, &b, 0) == -1)))
        !          3554:                                        msyslog(LOG_ERR,
        !          3555:                                                "Bad file descriptor %d",
        !          3556:                                                j);
        !          3557:                }
        !          3558:                return;
        !          3559:        }
        !          3560:        else if (n == 0)
        !          3561:                return;
        !          3562: 
        !          3563:        ++handler_pkts;
        !          3564: 
        !          3565: #ifdef REFCLOCK
        !          3566:        /*
        !          3567:         * Check out the reference clocks first, if any
        !          3568:         */
        !          3569: 
        !          3570:        if (refio != NULL) {
        !          3571:                register struct refclockio *rp;
        !          3572: 
        !          3573:                for (rp = refio; rp != NULL; rp = rp->next) {
        !          3574:                        fd = rp->fd;
        !          3575: 
        !          3576:                        if (FD_ISSET(fd, &fds))
        !          3577:                                do {
        !          3578:                                        ++select_count;
        !          3579:                                        buflen = read_refclock_packet(
        !          3580:                                                        fd, rp, ts);
        !          3581:                                } while (buflen > 0);
        !          3582:                }
        !          3583:        }
        !          3584: #endif /* REFCLOCK */
        !          3585: 
        !          3586:        /*
        !          3587:         * Loop through the interfaces looking for data to read.
        !          3588:         */
        !          3589:        for (ep = ep_list; ep != NULL; ep = ep->elink) {
        !          3590:                for (doing = 0; doing < 2; doing++) {
        !          3591:                        if (!doing) {
        !          3592:                                fd = ep->fd;
        !          3593:                        } else {
        !          3594:                                if (!(ep->flags & INT_BCASTOPEN))
        !          3595:                                        break;
        !          3596:                                fd = ep->bfd;
        !          3597:                        }
        !          3598:                        if (fd < 0)
        !          3599:                                continue;
        !          3600:                        if (FD_ISSET(fd, &fds))
        !          3601:                                do {
        !          3602:                                        ++select_count;
        !          3603:                                        buflen = read_network_packet(
        !          3604:                                                        fd, ep, ts);
        !          3605:                                } while (buflen > 0);
        !          3606:                        /* Check more interfaces */
        !          3607:                }
        !          3608:        }
        !          3609: 
        !          3610: #ifdef HAS_ROUTING_SOCKET
        !          3611:        /*
        !          3612:         * scan list of asyncio readers - currently only used for routing sockets
        !          3613:         */
        !          3614:        asyncio_reader = asyncio_reader_list;
        !          3615: 
        !          3616:        while (asyncio_reader != NULL) {
        !          3617:                if (FD_ISSET(asyncio_reader->fd, &fds)) {
        !          3618:                        ++select_count;
        !          3619:                        (asyncio_reader->receiver)(asyncio_reader);
        !          3620:                }
        !          3621:                asyncio_reader = asyncio_reader->link;
        !          3622:        }
        !          3623: #endif /* HAS_ROUTING_SOCKET */
        !          3624:        
        !          3625:        /*
        !          3626:         * Done everything from that select.
        !          3627:         */
        !          3628: 
        !          3629:        /*
        !          3630:         * If nothing to do, just return.
        !          3631:         * If an error occurred, complain and return.
        !          3632:         */
        !          3633:        if (select_count == 0) { /* We really had nothing to do */
        !          3634: #ifdef DEBUG
        !          3635:                if (debug)
        !          3636:                        msyslog(LOG_DEBUG, "input_handler: select() returned 0");
        !          3637: #endif
        !          3638:                return;
        !          3639:        }
        !          3640:        /* We've done our work */
        !          3641: #ifdef DEBUG_TIMING
        !          3642:        get_systime(&ts_e);
        !          3643:        /*
        !          3644:         * (ts_e - ts) is the amount of time we spent
        !          3645:         * processing this gob of file descriptors.  Log
        !          3646:         * it.
        !          3647:         */
        !          3648:        L_SUB(&ts_e, &ts);
        !          3649:        collect_timing(NULL, "input handler", 1, &ts_e);
        !          3650:        if (debug > 3)
        !          3651:                msyslog(LOG_DEBUG,
        !          3652:                        "input_handler: Processed a gob of fd's in %s msec",
        !          3653:                        lfptoms(&ts_e, 6));
        !          3654: #endif
        !          3655:        /* just bail. */
        !          3656:        return;
        !          3657: }
        !          3658: #endif
        !          3659: 
        !          3660: /*
        !          3661:  * findinterface - find local interface corresponding to address
        !          3662:  */
        !          3663: endpt *
        !          3664: findinterface(
        !          3665:        sockaddr_u *addr
        !          3666:        )
        !          3667: {
        !          3668:        endpt *iface;
        !          3669:        
        !          3670:        iface = findlocalinterface(addr, INT_WILDCARD, 0);
        !          3671: 
        !          3672:        if (NULL == iface) {
        !          3673:                DPRINTF(4, ("Found no interface for address %s - returning wildcard\n",
        !          3674:                            stoa(addr)));
        !          3675: 
        !          3676:                iface = ANY_INTERFACE_CHOOSE(addr);
        !          3677:        } else
        !          3678:                DPRINTF(4, ("Found interface #%d %s for address %s\n",
        !          3679:                            iface->ifnum, iface->name, stoa(addr)));
        !          3680: 
        !          3681:        return iface;
        !          3682: }
        !          3683: 
        !          3684: /*
        !          3685:  * findlocalinterface - find local interface corresponding to addr,
        !          3686:  * which does not have any of flags set.  If bast is nonzero, addr is
        !          3687:  * a broadcast address.
        !          3688:  *
        !          3689:  * This code attempts to find the local sending address for an outgoing
        !          3690:  * address by connecting a new socket to destinationaddress:NTP_PORT
        !          3691:  * and reading the sockname of the resulting connect.
        !          3692:  * the complicated sequence simulates the routing table lookup
        !          3693:  * for to first hop without duplicating any of the routing logic into
        !          3694:  * ntpd. preferably we would have used an API call - but its not there -
        !          3695:  * so this is the best we can do here short of duplicating to entire routing
        !          3696:  * logic in ntpd which would be a silly and really unportable thing to do.
        !          3697:  *
        !          3698:  */
        !          3699: static endpt *
        !          3700: findlocalinterface(
        !          3701:        sockaddr_u *    addr,
        !          3702:        int             flags,
        !          3703:        int             bcast
        !          3704:        )
        !          3705: {
        !          3706:        GETSOCKNAME_SOCKLEN_TYPE        sockaddrlen;
        !          3707:        endpt *                         iface;
        !          3708:        sockaddr_u                      saddr;
        !          3709:        SOCKET                          s;
        !          3710:        int                             rtn;
        !          3711:        int                             on;
        !          3712: 
        !          3713:        DPRINTF(4, ("Finding interface for addr %s in list of addresses\n",
        !          3714:                    stoa(addr)));
        !          3715:        
        !          3716:        s = socket(AF(addr), SOCK_DGRAM, 0);
        !          3717:        if (INVALID_SOCKET == s)
        !          3718:                return NULL;
        !          3719: 
        !          3720:        /*
        !          3721:         * If we are looking for broadcast interface we need to set this
        !          3722:         * socket to allow broadcast
        !          3723:         */
        !          3724:        if (bcast) {
        !          3725:                on = 1;
        !          3726:                setsockopt(s, SOL_SOCKET, SO_BROADCAST,
        !          3727:                           (char *)&on, sizeof(on));
        !          3728:        }
        !          3729: 
        !          3730:        rtn = connect(s, &addr->sa, SOCKLEN(addr));
        !          3731:        if (SOCKET_ERROR == rtn) {
        !          3732:                closesocket(s);
        !          3733:                return NULL;
        !          3734:        }
        !          3735: 
        !          3736:        sockaddrlen = sizeof(saddr);
        !          3737:        rtn = getsockname(s, &saddr.sa, &sockaddrlen);
        !          3738:        closesocket(s);
        !          3739:        if (SOCKET_ERROR == rtn)
        !          3740:                return NULL;
        !          3741: 
        !          3742:        DPRINTF(4, ("findlocalinterface: kernel maps %s to %s\n",
        !          3743:                    stoa(addr), stoa(&saddr)));
        !          3744:        
        !          3745:        iface = getinterface(&saddr, flags);
        !          3746: 
        !          3747:        /* 
        !          3748:         * if we didn't find an exact match on saddr, find the closest
        !          3749:         * available local address.  This handles the case of the
        !          3750:         * address suggested by the kernel being excluded by nic rules
        !          3751:         * or the user's -I and -L options to ntpd.
        !          3752:         * See http://bugs.ntp.org/1184 and http://bugs.ntp.org/1683
        !          3753:         * for more background.
        !          3754:         */
        !          3755:        if (NULL == iface || iface->ignore_packets)
        !          3756:                iface = findclosestinterface(&saddr, 
        !          3757:                                             flags | INT_LOOPBACK);
        !          3758: 
        !          3759:        /* Don't use an interface which will ignore replies */
        !          3760:        if (iface != NULL && iface->ignore_packets)
        !          3761:                iface = NULL;
        !          3762: 
        !          3763:        return iface;
        !          3764: }
        !          3765: 
        !          3766: 
        !          3767: /*
        !          3768:  * findclosestinterface
        !          3769:  *
        !          3770:  * If there are -I/--interface or -L/novirtualips command-line options,
        !          3771:  * or "nic" or "interface" rules in ntp.conf, findlocalinterface() may
        !          3772:  * find the kernel's preferred local address for a given peer address is
        !          3773:  * administratively unavailable to ntpd, and punt to this routine's more
        !          3774:  * expensive search.
        !          3775:  *
        !          3776:  * Find the numerically closest local address to the one connect()
        !          3777:  * suggested.  This matches an address on the same subnet first, as
        !          3778:  * needed by Bug 1184, and provides a consistent choice if there are
        !          3779:  * multiple feasible local addresses, regardless of the order ntpd
        !          3780:  * enumerated them.
        !          3781:  */
        !          3782: static endpt *
        !          3783: findclosestinterface(
        !          3784:        sockaddr_u *    addr,
        !          3785:        int             flags
        !          3786:        )
        !          3787: {
        !          3788:        endpt *         ep;
        !          3789:        endpt *         winner;
        !          3790:        sockaddr_u      addr_dist;
        !          3791:        sockaddr_u      min_dist;
        !          3792: 
        !          3793:        winner = NULL;
        !          3794:        
        !          3795:        for (ep = ep_list; ep != NULL; ep = ep->elink) {
        !          3796:                if (ep->ignore_packets ||
        !          3797:                    AF(addr) != ep->family || 
        !          3798:                    flags & ep->flags)
        !          3799:                        continue;
        !          3800:                
        !          3801:                calc_addr_distance(&addr_dist, addr, &ep->sin);
        !          3802:                if (NULL == winner ||
        !          3803:                    -1 == cmp_addr_distance(&addr_dist, &min_dist)) {
        !          3804:                        min_dist = addr_dist;
        !          3805:                        winner = ep;
        !          3806:                }
        !          3807:        }
        !          3808:        if (NULL == winner)
        !          3809:                DPRINTF(4, ("findclosestinterface(%s) failed\n", 
        !          3810:                            stoa(addr)));
        !          3811:        else
        !          3812:                DPRINTF(4, ("findclosestinterface(%s) -> %s\n", 
        !          3813:                            stoa(addr), stoa(&winner->sin)));
        !          3814: 
        !          3815:        return winner;
        !          3816: }
        !          3817: 
        !          3818: 
        !          3819: /*
        !          3820:  * calc_addr_distance - calculate the distance between two addresses,
        !          3821:  *                     the absolute value of the difference between
        !          3822:  *                     the addresses numerically, stored as an address.
        !          3823:  */
        !          3824: static void
        !          3825: calc_addr_distance(
        !          3826:        sockaddr_u *            dist,
        !          3827:        const sockaddr_u *      a1,
        !          3828:        const sockaddr_u *      a2
        !          3829:        )
        !          3830: {
        !          3831:        u_int32 a1val;
        !          3832:        u_int32 a2val;
        !          3833:        u_int32 v4dist;
        !          3834:        int     found_greater;
        !          3835:        int     a1_greater;
        !          3836:        int     i;
        !          3837: 
        !          3838:        NTP_REQUIRE(AF(a1) == AF(a2));
        !          3839: 
        !          3840:        memset(dist, 0, sizeof(*dist));
        !          3841:        AF(dist) = AF(a1);
        !          3842: 
        !          3843:        /* v4 can be done a bit simpler */
        !          3844:        if (IS_IPV4(a1)) {
        !          3845:                a1val = SRCADR(a1);
        !          3846:                a2val = SRCADR(a2);
        !          3847:                v4dist = (a1val > a2val)
        !          3848:                             ? a1val - a2val
        !          3849:                             : a2val - a1val;
        !          3850:                SET_ADDR4(dist, v4dist);
        !          3851: 
        !          3852:                return;
        !          3853:        }
        !          3854: 
        !          3855:        found_greater = FALSE;
        !          3856:        a1_greater = FALSE;     /* suppress pot. uninit. warning */
        !          3857:        for (i = 0; i < sizeof(NSRCADR6(a1)); i++) {
        !          3858:                if (!found_greater &&
        !          3859:                    NSRCADR6(a1)[i] != NSRCADR6(a2)[i]) {
        !          3860:                        found_greater = TRUE;
        !          3861:                        a1_greater = (NSRCADR6(a1)[i] > NSRCADR6(a2)[i]);
        !          3862:                }
        !          3863:                if (!found_greater) {
        !          3864:                        NSRCADR6(dist)[i] = 0;
        !          3865:                } else {
        !          3866:                        if (a1_greater)
        !          3867:                                NSRCADR6(dist)[i] = NSRCADR6(a1)[i] -
        !          3868:                                                    NSRCADR6(a2)[i];
        !          3869:                        else
        !          3870:                                NSRCADR6(dist)[i] = NSRCADR6(a2)[i] -
        !          3871:                                                    NSRCADR6(a1)[i];
        !          3872:                }
        !          3873:        }
        !          3874: }
        !          3875: 
        !          3876: 
        !          3877: /*
        !          3878:  * cmp_addr_distance - compare two address distances, returning -1, 0,
        !          3879:  *                    1 to indicate their relationship.
        !          3880:  */
        !          3881: static int
        !          3882: cmp_addr_distance(
        !          3883:        const sockaddr_u *      d1,
        !          3884:        const sockaddr_u *      d2
        !          3885:        )
        !          3886: {
        !          3887:        int     i;
        !          3888: 
        !          3889:        NTP_REQUIRE(AF(d1) == AF(d2));
        !          3890: 
        !          3891:        if (IS_IPV4(d1)) {
        !          3892:                if (SRCADR(d1) < SRCADR(d2))
        !          3893:                        return -1;
        !          3894:                else if (SRCADR(d1) == SRCADR(d2))
        !          3895:                        return 0;
        !          3896:                else
        !          3897:                        return 1;
        !          3898:        }
        !          3899: 
        !          3900:        for (i = 0; i < sizeof(NSRCADR6(d1)); i++) {
        !          3901:                if (NSRCADR6(d1)[i] < NSRCADR6(d2)[i])
        !          3902:                        return -1;
        !          3903:                else if (NSRCADR6(d1)[i] > NSRCADR6(d2)[i])
        !          3904:                        return 1;
        !          3905:        }
        !          3906: 
        !          3907:        return 0;
        !          3908: }
        !          3909: 
        !          3910: 
        !          3911: 
        !          3912: /*
        !          3913:  * fetch an interface structure the matches the
        !          3914:  * address and has the given flags NOT set
        !          3915:  */
        !          3916: static endpt *
        !          3917: getinterface(
        !          3918:        sockaddr_u *    addr, 
        !          3919:        u_int32         flags
        !          3920:        )
        !          3921: {
        !          3922:        endpt *iface;
        !          3923:        
        !          3924:        iface = find_addr_in_list(addr);
        !          3925: 
        !          3926:        if (iface != NULL && (iface->flags & flags))
        !          3927:                iface = NULL;
        !          3928:        
        !          3929:        return iface;
        !          3930: }
        !          3931: 
        !          3932: 
        !          3933: /*
        !          3934:  * findbcastinter - find broadcast interface corresponding to address
        !          3935:  */
        !          3936: endpt *
        !          3937: findbcastinter(
        !          3938:        sockaddr_u *addr
        !          3939:        )
        !          3940: {
        !          3941: #if !defined(MPE) && (defined(SIOCGIFCONF) || defined(SYS_WINNT))
        !          3942:        struct interface *iface;
        !          3943:        
        !          3944:        
        !          3945:        DPRINTF(4, ("Finding broadcast/multicast interface for addr %s in list of addresses\n",
        !          3946:                    stoa(addr)));
        !          3947: 
        !          3948:        iface = findlocalinterface(addr, INT_LOOPBACK | INT_WILDCARD,
        !          3949:                                   1);  
        !          3950:        if (iface != NULL) {
        !          3951:                DPRINTF(4, ("Easily found bcast-/mcast- interface index #%d %s\n",
        !          3952:                            iface->ifnum, iface->name));
        !          3953:                return iface;
        !          3954:        }
        !          3955: 
        !          3956:        /*
        !          3957:         * plan B - try to find something reasonable in our lists in
        !          3958:         * case kernel lookup doesn't help
        !          3959:         */
        !          3960:        for (iface = ep_list; iface != NULL; iface = iface->elink) {
        !          3961:                if (iface->flags & INT_WILDCARD)
        !          3962:                        continue;
        !          3963:                
        !          3964:                /* Don't bother with ignored interfaces */
        !          3965:                if (iface->ignore_packets)
        !          3966:                        continue;
        !          3967:                
        !          3968:                /*
        !          3969:                 * First look if this is the correct family
        !          3970:                 */
        !          3971:                if(AF(&iface->sin) != AF(addr))
        !          3972:                        continue;
        !          3973: 
        !          3974:                /* Skip the loopback addresses */
        !          3975:                if (iface->flags & INT_LOOPBACK)
        !          3976:                        continue;
        !          3977: 
        !          3978:                /*
        !          3979:                 * If we are looking to match a multicast address and
        !          3980:                 * this interface is one...
        !          3981:                 */
        !          3982:                if (addr_ismulticast(addr) 
        !          3983:                    && (iface->flags & INT_MULTICAST)) {
        !          3984: #ifdef INCLUDE_IPV6_SUPPORT
        !          3985:                        /*
        !          3986:                         * ...it is the winner unless we're looking for
        !          3987:                         * an interface to use for link-local multicast
        !          3988:                         * and its address is not link-local.
        !          3989:                         */
        !          3990:                        if (IS_IPV6(addr)
        !          3991:                            && IN6_IS_ADDR_MC_LINKLOCAL(PSOCK_ADDR6(addr))
        !          3992:                            && !IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(&iface->sin)))
        !          3993:                                continue;
        !          3994: #endif
        !          3995:                        break;
        !          3996:                }
        !          3997: 
        !          3998:                /*
        !          3999:                 * We match only those interfaces marked as
        !          4000:                 * broadcastable and either the explicit broadcast
        !          4001:                 * address or the network portion of the IP address.
        !          4002:                 * Sloppy.
        !          4003:                 */
        !          4004:                if (IS_IPV4(addr)) {
        !          4005:                        if (SOCK_EQ(&iface->bcast, addr))
        !          4006:                                break;
        !          4007: 
        !          4008:                        if ((NSRCADR(&iface->sin) & NSRCADR(&iface->mask)) 
        !          4009:                            == (NSRCADR(addr)     & NSRCADR(&iface->mask)))
        !          4010:                                break;
        !          4011:                }
        !          4012: #ifdef INCLUDE_IPV6_SUPPORT
        !          4013:                else if (IS_IPV6(addr)) {
        !          4014:                        if (SOCK_EQ(&iface->bcast, addr))
        !          4015:                                break;
        !          4016: 
        !          4017:                        if (SOCK_EQ(netof(&iface->sin), netof(addr)))
        !          4018:                                break;
        !          4019:                }
        !          4020: #endif
        !          4021:        }
        !          4022: #endif /* SIOCGIFCONF */
        !          4023:        if (NULL == iface) {
        !          4024:                DPRINTF(4, ("No bcast interface found for %s\n",
        !          4025:                            stoa(addr)));
        !          4026:                iface = ANY_INTERFACE_CHOOSE(addr);
        !          4027:        } else
        !          4028:                DPRINTF(4, ("Found bcast-/mcast- interface index #%d %s\n",
        !          4029:                            iface->ifnum, iface->name));
        !          4030:        return iface;
        !          4031: }
        !          4032: 
        !          4033: 
        !          4034: /*
        !          4035:  * io_clr_stats - clear I/O module statistics
        !          4036:  */
        !          4037: void
        !          4038: io_clr_stats(void)
        !          4039: {
        !          4040:        packets_dropped = 0;
        !          4041:        packets_ignored = 0;
        !          4042:        packets_received = 0;
        !          4043:        packets_sent = 0;
        !          4044:        packets_notsent = 0;
        !          4045: 
        !          4046:        handler_calls = 0;
        !          4047:        handler_pkts = 0;
        !          4048:        io_timereset = current_time;
        !          4049: }
        !          4050: 
        !          4051: 
        !          4052: #ifdef REFCLOCK
        !          4053: /*
        !          4054:  * io_addclock - add a reference clock to the list and arrange that we
        !          4055:  *                              get SIGIO interrupts from it.
        !          4056:  */
        !          4057: int
        !          4058: io_addclock(
        !          4059:        struct refclockio *rio
        !          4060:        )
        !          4061: {
        !          4062:        BLOCKIO();
        !          4063: 
        !          4064:        /*
        !          4065:         * Stuff the I/O structure in the list and mark the descriptor
        !          4066:         * in use.  There is a harmless (I hope) race condition here.
        !          4067:         */
        !          4068:        rio->next = refio;
        !          4069: 
        !          4070: # ifdef HAVE_SIGNALED_IO
        !          4071:        if (init_clock_sig(rio)) {
        !          4072:                UNBLOCKIO();
        !          4073:                return 0;
        !          4074:        }
        !          4075: # elif defined(HAVE_IO_COMPLETION_PORT)
        !          4076:        if (io_completion_port_add_clock_io(rio)) {
        !          4077:                UNBLOCKIO();
        !          4078:                return 0;
        !          4079:        }
        !          4080: # endif
        !          4081: 
        !          4082:        /*
        !          4083:         * enqueue
        !          4084:         */
        !          4085:        refio = rio;
        !          4086: 
        !          4087:        /*
        !          4088:         * register fd
        !          4089:         */
        !          4090:        add_fd_to_list(rio->fd, FD_TYPE_FILE);
        !          4091: 
        !          4092:        UNBLOCKIO();
        !          4093:        return 1;
        !          4094: }
        !          4095: 
        !          4096: /*
        !          4097:  * io_closeclock - close the clock in the I/O structure given
        !          4098:  */
        !          4099: void
        !          4100: io_closeclock(
        !          4101:        struct refclockio *rio
        !          4102:        )
        !          4103: {
        !          4104:        register struct refclockio *rp;
        !          4105: 
        !          4106:        BLOCKIO();
        !          4107: 
        !          4108:        /*
        !          4109:         * Remove structure from the list
        !          4110:         */
        !          4111:        if (refio == rio)
        !          4112:                refio = rio->next;
        !          4113:        else {
        !          4114:                for (rp = refio; rp != NULL; rp = rp->next)
        !          4115:                        if (rp->next == rio) {
        !          4116:                                rp->next = rio->next;
        !          4117:                                break;
        !          4118:                        }
        !          4119: 
        !          4120:                if (NULL == rp) {
        !          4121:                        UNBLOCKIO();
        !          4122:                        return;
        !          4123:                }
        !          4124:        }
        !          4125: 
        !          4126:        /*
        !          4127:         * Close the descriptor.
        !          4128:         */
        !          4129:        close_and_delete_fd_from_list(rio->fd);
        !          4130:        UNBLOCKIO();
        !          4131: }
        !          4132: #endif /* REFCLOCK */
        !          4133: 
        !          4134: /*
        !          4135:  * On NT a SOCKET is an unsigned int so we cannot possibly keep it in
        !          4136:  * an array. So we use one of the ISC_LIST functions to hold the
        !          4137:  * socket value and use that when we want to enumerate it.
        !          4138:  *
        !          4139:  * This routine is called by the forked intres child process to close
        !          4140:  * all open sockets.  On Windows there's no need as intres runs in
        !          4141:  * the same process as a thread.
        !          4142:  */
        !          4143: #ifndef SYS_WINNT
        !          4144: void
        !          4145: kill_asyncio(int startfd)
        !          4146: {
        !          4147:        BLOCKIO();
        !          4148: 
        !          4149:        /*
        !          4150:         * In the child process we do not maintain activefds and
        !          4151:         * maxactivefd.  Zeroing maxactivefd disables code which
        !          4152:         * maintains it in close_and_delete_fd_from_list().
        !          4153:         */
        !          4154:        maxactivefd = 0;
        !          4155: 
        !          4156:        while (fd_list != NULL)
        !          4157:                close_and_delete_fd_from_list(fd_list->fd);
        !          4158: 
        !          4159:        UNBLOCKIO();
        !          4160: }
        !          4161: #endif /* !SYS_WINNT */
        !          4162: 
        !          4163: /*
        !          4164:  * Add and delete functions for the list of open sockets
        !          4165:  */
        !          4166: static void
        !          4167: add_fd_to_list(
        !          4168:        SOCKET fd,
        !          4169:        enum desc_type type
        !          4170:        )
        !          4171: {
        !          4172:        vsock_t *lsock = emalloc(sizeof(*lsock));
        !          4173: 
        !          4174:        lsock->fd = fd;
        !          4175:        lsock->type = type;
        !          4176: 
        !          4177:        LINK_SLIST(fd_list, lsock, link);
        !          4178:        /*
        !          4179:         * I/O Completion Ports don't care about the select and FD_SET
        !          4180:         */
        !          4181: #ifndef HAVE_IO_COMPLETION_PORT
        !          4182:        if (fd < 0 || fd >= FD_SETSIZE) {
        !          4183:                msyslog(LOG_ERR,
        !          4184:                        "Too many sockets in use, FD_SETSIZE %d exceeded",
        !          4185:                        FD_SETSIZE);
        !          4186:                exit(1);
        !          4187:        }
        !          4188:        /*
        !          4189:         * keep activefds in sync
        !          4190:         */
        !          4191:        maxactivefd = max(fd, maxactivefd);
        !          4192: 
        !          4193:        FD_SET(fd, &activefds);
        !          4194: #endif
        !          4195: }
        !          4196: 
        !          4197: static void
        !          4198: close_and_delete_fd_from_list(
        !          4199:        SOCKET fd
        !          4200:        ) 
        !          4201: {
        !          4202:        vsock_t *lsock;
        !          4203: 
        !          4204:        UNLINK_EXPR_SLIST(lsock, fd_list, fd == 
        !          4205:            UNLINK_EXPR_SLIST_CURRENT()->fd, link, vsock_t);
        !          4206: 
        !          4207:        if (lsock != NULL) {
        !          4208:                switch (lsock->type) {
        !          4209:                case FD_TYPE_SOCKET:
        !          4210:                        closesocket(lsock->fd);
        !          4211:                        break;
        !          4212: 
        !          4213:                case FD_TYPE_FILE:
        !          4214:                        close(lsock->fd);
        !          4215:                        break;
        !          4216: 
        !          4217:                default:
        !          4218:                        msyslog(LOG_ERR,
        !          4219:                                "internal error - illegal descriptor type %d - EXITING",
        !          4220:                                (int)lsock->type);
        !          4221:                        exit(1);
        !          4222:                }
        !          4223: 
        !          4224:                free(lsock);
        !          4225:                /*
        !          4226:                 * I/O Completion Ports don't care about select and fd_set
        !          4227:                 */
        !          4228: #ifndef HAVE_IO_COMPLETION_PORT
        !          4229:                /*
        !          4230:                 * remove from activefds
        !          4231:                 */
        !          4232:                FD_CLR(fd, &activefds);
        !          4233:                
        !          4234:                if (fd == maxactivefd && maxactivefd) {
        !          4235:                        int i;
        !          4236:                        NTP_INSIST(maxactivefd - 1 < FD_SETSIZE);
        !          4237:                        for (i = maxactivefd - 1; i >= 0; i--)
        !          4238:                                if (FD_ISSET(i, &activefds)) {
        !          4239:                                        maxactivefd = i;
        !          4240:                                        break;
        !          4241:                                }
        !          4242:                        NTP_INSIST(fd != maxactivefd);
        !          4243:                }
        !          4244: #endif
        !          4245:        }
        !          4246: }
        !          4247: 
        !          4248: static void
        !          4249: add_addr_to_list(
        !          4250:        sockaddr_u *    addr,
        !          4251:        endpt *         ep
        !          4252:        )
        !          4253: {
        !          4254:        remaddr_t *laddr;
        !          4255: 
        !          4256: #ifdef DEBUG
        !          4257:        if (find_addr_in_list(addr) == NULL) {
        !          4258: #endif
        !          4259:                /* not there yet - add to list */
        !          4260:                laddr = emalloc(sizeof(*laddr));
        !          4261:                laddr->addr = *addr;
        !          4262:                laddr->ep = ep;
        !          4263:                
        !          4264:                LINK_SLIST(remoteaddr_list, laddr, link);
        !          4265:                
        !          4266:                DPRINTF(4, ("Added addr %s to list of addresses\n",
        !          4267:                            stoa(addr)));
        !          4268: #ifdef DEBUG
        !          4269:        } else
        !          4270:                DPRINTF(4, ("WARNING: Attempt to add duplicate addr %s to address list\n",
        !          4271:                            stoa(addr)));
        !          4272: #endif
        !          4273: }
        !          4274: 
        !          4275: 
        !          4276: static void
        !          4277: delete_addr_from_list(
        !          4278:        sockaddr_u *addr
        !          4279:        ) 
        !          4280: {
        !          4281:        remaddr_t *unlinked;
        !          4282:        
        !          4283:        UNLINK_EXPR_SLIST(unlinked, remoteaddr_list, SOCK_EQ(addr,
        !          4284:                &(UNLINK_EXPR_SLIST_CURRENT()->addr)), link, remaddr_t);
        !          4285: 
        !          4286:        if (unlinked != NULL) {
        !          4287:                DPRINTF(4, ("Deleted addr %s from list of addresses\n",
        !          4288:                        stoa(addr)));
        !          4289:                free(unlinked);
        !          4290:        }
        !          4291: }
        !          4292: 
        !          4293: 
        !          4294: static void
        !          4295: delete_interface_from_list(
        !          4296:        endpt *iface
        !          4297:        )
        !          4298: {
        !          4299:        remaddr_t *unlinked;
        !          4300: 
        !          4301:        do {
        !          4302:                UNLINK_EXPR_SLIST(unlinked, remoteaddr_list, iface ==
        !          4303:                    UNLINK_EXPR_SLIST_CURRENT()->ep, link,
        !          4304:                    remaddr_t);
        !          4305: 
        !          4306:                if (unlinked != NULL) {
        !          4307:                        DPRINTF(4, ("Deleted addr %s for interface #%d %s from list of addresses\n",
        !          4308:                                stoa(&unlinked->addr), iface->ifnum,
        !          4309:                                iface->name));
        !          4310:                        free(unlinked);
        !          4311:                }
        !          4312:        } while (unlinked != NULL);
        !          4313: }
        !          4314: 
        !          4315: 
        !          4316: static struct interface *
        !          4317: find_addr_in_list(
        !          4318:        sockaddr_u *addr
        !          4319:        ) 
        !          4320: {
        !          4321:        remaddr_t *entry;
        !          4322:        
        !          4323:        DPRINTF(4, ("Searching for addr %s in list of addresses - ",
        !          4324:                    stoa(addr)));
        !          4325: 
        !          4326:        for (entry = remoteaddr_list;
        !          4327:             entry != NULL;
        !          4328:             entry = entry->link)
        !          4329:                if (SOCK_EQ(&entry->addr, addr)) {
        !          4330:                        DPRINTF(4, ("FOUND\n"));
        !          4331:                        return entry->ep;
        !          4332:                }
        !          4333: 
        !          4334:        DPRINTF(4, ("NOT FOUND\n"));
        !          4335:        return NULL;
        !          4336: }
        !          4337: 
        !          4338: 
        !          4339: /*
        !          4340:  * Find the given address with the all given flags set in the list
        !          4341:  */
        !          4342: static endpt *
        !          4343: find_flagged_addr_in_list(
        !          4344:        sockaddr_u *    addr,
        !          4345:        u_int32         flags
        !          4346:        )
        !          4347: {
        !          4348:        remaddr_t *entry;
        !          4349:        
        !          4350:        DPRINTF(4, ("Finding addr %s with flags %d in list: ",
        !          4351:                    stoa(addr), flags));
        !          4352: 
        !          4353:        for (entry = remoteaddr_list;
        !          4354:             entry != NULL;
        !          4355:             entry = entry->link)
        !          4356: 
        !          4357:                if (SOCK_EQ(&entry->addr, addr)
        !          4358:                    && (entry->ep->flags & flags) == flags) {
        !          4359: 
        !          4360:                        DPRINTF(4, ("FOUND\n"));
        !          4361:                        return entry->ep;
        !          4362:                }
        !          4363: 
        !          4364:        DPRINTF(4, ("NOT FOUND\n"));
        !          4365:        return NULL;
        !          4366: }
        !          4367: 
        !          4368: 
        !          4369: const char *
        !          4370: localaddrtoa(
        !          4371:        endpt *la
        !          4372:        )
        !          4373: {
        !          4374:        return (NULL == la)
        !          4375:                   ? "<null>"
        !          4376:                   : stoa(&la->sin);
        !          4377: }
        !          4378: 
        !          4379: 
        !          4380: #ifdef HAS_ROUTING_SOCKET
        !          4381: # ifndef UPDATE_GRACE
        !          4382: #  define UPDATE_GRACE 2       /* wait UPDATE_GRACE seconds before scanning */
        !          4383: # endif
        !          4384: 
        !          4385: static void
        !          4386: process_routing_msgs(struct asyncio_reader *reader)
        !          4387: {
        !          4388:        char buffer[5120];
        !          4389:        int cnt, msg_type;
        !          4390: #ifdef HAVE_RTNETLINK
        !          4391:        struct nlmsghdr *nh;
        !          4392: #else
        !          4393:        struct rt_msghdr *rtm;
        !          4394:        char *p;
        !          4395: #endif
        !          4396:        
        !          4397:        if (disable_dynamic_updates) {
        !          4398:                /*
        !          4399:                 * discard ourselves if we are not needed any more
        !          4400:                 * usually happens when running unprivileged
        !          4401:                 */
        !          4402:                remove_asyncio_reader(reader);
        !          4403:                delete_asyncio_reader(reader);
        !          4404:                return;
        !          4405:        }
        !          4406: 
        !          4407:        cnt = read(reader->fd, buffer, sizeof(buffer));
        !          4408:        
        !          4409:        if (cnt < 0) {
        !          4410:                msyslog(LOG_ERR,
        !          4411:                        "i/o error on routing socket %m - disabling");
        !          4412:                remove_asyncio_reader(reader);
        !          4413:                delete_asyncio_reader(reader);
        !          4414:                return;
        !          4415:        }
        !          4416: 
        !          4417:        /*
        !          4418:         * process routing message
        !          4419:         */
        !          4420: #ifdef HAVE_RTNETLINK
        !          4421:        for (nh = (struct nlmsghdr *)buffer;
        !          4422:             NLMSG_OK(nh, cnt);
        !          4423:             nh = NLMSG_NEXT(nh, cnt)) {
        !          4424:                msg_type = nh->nlmsg_type;
        !          4425: #else
        !          4426:        for (p = buffer;
        !          4427:             (p + sizeof(struct rt_msghdr)) <= (buffer + cnt);
        !          4428:             p += rtm->rtm_msglen) {
        !          4429:                rtm = (struct rt_msghdr *)p;
        !          4430:                if (rtm->rtm_version != RTM_VERSION) {
        !          4431:                        msyslog(LOG_ERR,
        !          4432:                                "version mismatch (got %d - expected %d) on routing socket - disabling",
        !          4433:                                rtm->rtm_version, RTM_VERSION);
        !          4434: 
        !          4435:                        remove_asyncio_reader(reader);
        !          4436:                        delete_asyncio_reader(reader);
        !          4437:                        return;
        !          4438:                }
        !          4439:                msg_type = rtm->rtm_type;
        !          4440: #endif
        !          4441:                switch (msg_type) {
        !          4442: #ifdef RTM_NEWADDR
        !          4443:                case RTM_NEWADDR:
        !          4444: #endif
        !          4445: #ifdef RTM_DELADDR
        !          4446:                case RTM_DELADDR:
        !          4447: #endif
        !          4448: #ifdef RTM_ADD
        !          4449:                case RTM_ADD:
        !          4450: #endif
        !          4451: #ifdef RTM_DELETE
        !          4452:                case RTM_DELETE:
        !          4453: #endif
        !          4454: #ifdef RTM_REDIRECT
        !          4455:                case RTM_REDIRECT:
        !          4456: #endif
        !          4457: #ifdef RTM_CHANGE
        !          4458:                case RTM_CHANGE:
        !          4459: #endif
        !          4460: #ifdef RTM_LOSING
        !          4461:                case RTM_LOSING:
        !          4462: #endif
        !          4463: #ifdef RTM_IFINFO
        !          4464:                case RTM_IFINFO:
        !          4465: #endif
        !          4466: #ifdef RTM_IFANNOUNCE
        !          4467:                case RTM_IFANNOUNCE:
        !          4468: #endif
        !          4469: #ifdef RTM_NEWLINK
        !          4470:                case RTM_NEWLINK:
        !          4471: #endif
        !          4472: #ifdef RTM_DELLINK
        !          4473:                case RTM_DELLINK:
        !          4474: #endif
        !          4475: #ifdef RTM_NEWROUTE
        !          4476:                case RTM_NEWROUTE:
        !          4477: #endif
        !          4478: #ifdef RTM_DELROUTE
        !          4479:                case RTM_DELROUTE:
        !          4480: #endif
        !          4481:                        /*
        !          4482:                         * we are keen on new and deleted addresses and
        !          4483:                         * if an interface goes up and down or routing
        !          4484:                         * changes
        !          4485:                         */
        !          4486:                        DPRINTF(3, ("routing message op = %d: scheduling interface update\n",
        !          4487:                                    msg_type));
        !          4488:                        timer_interfacetimeout(current_time + UPDATE_GRACE);
        !          4489:                        break;
        !          4490: #ifdef HAVE_RTNETLINK
        !          4491:                case NLMSG_DONE:
        !          4492:                        /* end of multipart message */
        !          4493:                        return;
        !          4494: #endif
        !          4495:                default:
        !          4496:                        /*
        !          4497:                         * the rest doesn't bother us.
        !          4498:                         */
        !          4499:                        DPRINTF(4, ("routing message op = %d: ignored\n",
        !          4500:                                    msg_type));
        !          4501:                        break;
        !          4502:                }
        !          4503:        }
        !          4504: }
        !          4505: 
        !          4506: /*
        !          4507:  * set up routing notifications
        !          4508:  */
        !          4509: static void
        !          4510: init_async_notifications()
        !          4511: {
        !          4512:        struct asyncio_reader *reader;
        !          4513: #ifdef HAVE_RTNETLINK
        !          4514:        int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
        !          4515:        struct sockaddr_nl sa;
        !          4516: #else
        !          4517:        int fd = socket(PF_ROUTE, SOCK_RAW, 0);
        !          4518: #endif
        !          4519:        if (fd < 0) {
        !          4520:                msyslog(LOG_ERR,
        !          4521:                        "unable to open routing socket (%m) - using polled interface update");
        !          4522:                return;
        !          4523:        }
        !          4524: 
        !          4525:        fd = move_fd(fd);
        !          4526: #ifdef HAVE_RTNETLINK
        !          4527:        memset(&sa, 0, sizeof(sa));
        !          4528:        sa.nl_family = PF_NETLINK;
        !          4529:        sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR
        !          4530:                       | RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_ROUTE
        !          4531:                       | RTMGRP_IPV4_MROUTE | RTMGRP_IPV6_ROUTE
        !          4532:                       | RTMGRP_IPV6_MROUTE;
        !          4533:        if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
        !          4534:                msyslog(LOG_ERR,
        !          4535:                        "bind failed on routing socket (%m) - using polled interface update");
        !          4536:                return;
        !          4537:        }
        !          4538: #endif
        !          4539:        init_nonblocking_io(fd);
        !          4540: #if defined(HAVE_SIGNALED_IO)
        !          4541:        init_socket_sig(fd);
        !          4542: #endif /* HAVE_SIGNALED_IO */
        !          4543:        
        !          4544:        reader = new_asyncio_reader();
        !          4545: 
        !          4546:        reader->fd = fd;
        !          4547:        reader->receiver = process_routing_msgs;
        !          4548:        
        !          4549:        add_asyncio_reader(reader, FD_TYPE_SOCKET);
        !          4550:        msyslog(LOG_INFO,
        !          4551:                "Listening on routing socket on fd #%d for interface updates",
        !          4552:                fd);
        !          4553: }
        !          4554: #else
        !          4555: /* HAS_ROUTING_SOCKET not defined */
        !          4556: static void
        !          4557: init_async_notifications(void)
        !          4558: {
        !          4559: }
        !          4560: #endif

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