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>