1*1c24ec91Schristos /* $NetBSD: ntp_io.c,v 1.25 2017/04/13 20:17:42 christos Exp $ */ 2abb0f93cSkardel 3abb0f93cSkardel /* 4abb0f93cSkardel * ntp_io.c - input/output routines for ntpd. The socket-opening code 5abb0f93cSkardel * was shamelessly stolen from ntpd. 6abb0f93cSkardel */ 7abb0f93cSkardel 8abb0f93cSkardel #ifdef HAVE_CONFIG_H 9abb0f93cSkardel # include <config.h> 10abb0f93cSkardel #endif 11abb0f93cSkardel 12abb0f93cSkardel #include <stdio.h> 13abb0f93cSkardel #include <signal.h> 14ad131110Schristos #ifdef HAVE_FNMATCH_H 15ad131110Schristos # include <fnmatch.h> 16ad131110Schristos # if !defined(FNM_CASEFOLD) && defined(FNM_IGNORECASE) 17ad131110Schristos # define FNM_CASEFOLD FNM_IGNORECASE 18ad131110Schristos # endif 19ad131110Schristos #endif 20abb0f93cSkardel #ifdef HAVE_SYS_PARAM_H 21abb0f93cSkardel # include <sys/param.h> 22abb0f93cSkardel #endif 23abb0f93cSkardel #ifdef HAVE_SYS_IOCTL_H 24abb0f93cSkardel # include <sys/ioctl.h> 25abb0f93cSkardel #endif 26abb0f93cSkardel #ifdef HAVE_SYS_SOCKIO_H /* UXPV: SIOC* #defines (Frank Vance <fvance@waii.com>) */ 27abb0f93cSkardel # include <sys/sockio.h> 28abb0f93cSkardel #endif 29abb0f93cSkardel #ifdef HAVE_SYS_UIO_H 30abb0f93cSkardel # include <sys/uio.h> 31abb0f93cSkardel #endif 32abb0f93cSkardel 33abb0f93cSkardel #include "ntp_machine.h" 34abb0f93cSkardel #include "ntpd.h" 35abb0f93cSkardel #include "ntp_io.h" 36abb0f93cSkardel #include "iosignal.h" 37abb0f93cSkardel #include "ntp_lists.h" 38abb0f93cSkardel #include "ntp_refclock.h" 39abb0f93cSkardel #include "ntp_stdlib.h" 40b3d6264cSchristos #include "ntp_worker.h" 41abb0f93cSkardel #include "ntp_request.h" 42abb0f93cSkardel #include "ntp_assert.h" 43b3d6264cSchristos #include "timevalops.h" 44b3d6264cSchristos #include "timespecops.h" 45abb0f93cSkardel #include "ntpd-opts.h" 46bd25f4c4Schristos #include "safecast.h" 47abb0f93cSkardel 48abb0f93cSkardel /* Don't include ISC's version of IPv6 variables and structures */ 49abb0f93cSkardel #define ISC_IPV6_H 1 50abb0f93cSkardel #include <isc/mem.h> 51abb0f93cSkardel #include <isc/interfaceiter.h> 52abb0f93cSkardel #include <isc/netaddr.h> 53abb0f93cSkardel #include <isc/result.h> 54abb0f93cSkardel #include <isc/sockaddr.h> 55abb0f93cSkardel 56abb0f93cSkardel #ifdef SIM 57abb0f93cSkardel #include "ntpsim.h" 58abb0f93cSkardel #endif 59abb0f93cSkardel 60abb0f93cSkardel #ifdef HAS_ROUTING_SOCKET 61abb0f93cSkardel # include <net/route.h> 62abb0f93cSkardel # ifdef HAVE_RTNETLINK 63abb0f93cSkardel # include <linux/rtnetlink.h> 64abb0f93cSkardel # endif 65abb0f93cSkardel #endif 66abb0f93cSkardel 67abb0f93cSkardel /* 68abb0f93cSkardel * setsockopt does not always have the same arg declaration 69abb0f93cSkardel * across all platforms. If it's not defined we make it empty 70abb0f93cSkardel */ 71abb0f93cSkardel 72abb0f93cSkardel #ifndef SETSOCKOPT_ARG_CAST 73abb0f93cSkardel #define SETSOCKOPT_ARG_CAST 74abb0f93cSkardel #endif 75abb0f93cSkardel 76abb0f93cSkardel extern int listen_to_virtual_ips; 77abb0f93cSkardel 784e3b3909Schristos #ifndef IPTOS_DSCP_EF 794e3b3909Schristos #define IPTOS_DSCP_EF 0xb8 804e3b3909Schristos #endif 814e3b3909Schristos int qos = IPTOS_DSCP_EF; /* QoS RFC3246 */ 824e3b3909Schristos 834e3b3909Schristos #ifdef LEAP_SMEAR 844e3b3909Schristos /* TODO burnicki: This should be moved to ntp_timer.c, but if we do so 854e3b3909Schristos * we get a linker error. Since we're running out of time before the leap 864e3b3909Schristos * second occurs, we let it here where it just works. 874e3b3909Schristos */ 884e3b3909Schristos int leap_smear_intv; 894e3b3909Schristos #endif 904e3b3909Schristos 91abb0f93cSkardel /* 92abb0f93cSkardel * NIC rule entry 93abb0f93cSkardel */ 94abb0f93cSkardel typedef struct nic_rule_tag nic_rule; 95abb0f93cSkardel 96abb0f93cSkardel struct nic_rule_tag { 97abb0f93cSkardel nic_rule * next; 98abb0f93cSkardel nic_rule_action action; 99abb0f93cSkardel nic_rule_match match_type; 100abb0f93cSkardel char * if_name; 10145530cf1Skardel sockaddr_u addr; 102abb0f93cSkardel int prefixlen; 103abb0f93cSkardel }; 104abb0f93cSkardel 105abb0f93cSkardel /* 106abb0f93cSkardel * NIC rule listhead. Entries are added at the head so that the first 107abb0f93cSkardel * match in the list is the last matching rule specified. 108abb0f93cSkardel */ 109abb0f93cSkardel nic_rule *nic_rule_list; 110abb0f93cSkardel 111abb0f93cSkardel 112b3d6264cSchristos #if defined(SO_BINTIME) && defined(SCM_BINTIME) && defined(CMSG_FIRSTHDR) 113b3d6264cSchristos # define HAVE_PACKET_TIMESTAMP 114b3d6264cSchristos # define HAVE_BINTIME 115b3d6264cSchristos # ifdef BINTIME_CTLMSGBUF_SIZE 116b3d6264cSchristos # define CMSG_BUFSIZE BINTIME_CTLMSGBUF_SIZE 117b3d6264cSchristos # else 118b3d6264cSchristos # define CMSG_BUFSIZE 1536 /* moderate default */ 119b3d6264cSchristos # endif 120b3d6264cSchristos #elif defined(SO_TIMESTAMPNS) && defined(SCM_TIMESTAMPNS) && defined(CMSG_FIRSTHDR) 121b3d6264cSchristos # define HAVE_PACKET_TIMESTAMP 122b3d6264cSchristos # define HAVE_TIMESTAMPNS 123b3d6264cSchristos # ifdef TIMESTAMPNS_CTLMSGBUF_SIZE 124b3d6264cSchristos # define CMSG_BUFSIZE TIMESTAMPNS_CTLMSGBUF_SIZE 125b3d6264cSchristos # else 126b3d6264cSchristos # define CMSG_BUFSIZE 1536 /* moderate default */ 127b3d6264cSchristos # endif 128b3d6264cSchristos #elif defined(SO_TIMESTAMP) && defined(SCM_TIMESTAMP) && defined(CMSG_FIRSTHDR) 129b3d6264cSchristos # define HAVE_PACKET_TIMESTAMP 130abb0f93cSkardel # define HAVE_TIMESTAMP 131b3d6264cSchristos # ifdef TIMESTAMP_CTLMSGBUF_SIZE 132b3d6264cSchristos # define CMSG_BUFSIZE TIMESTAMP_CTLMSGBUF_SIZE 133b3d6264cSchristos # else 134b3d6264cSchristos # define CMSG_BUFSIZE 1536 /* moderate default */ 135abb0f93cSkardel # endif 136abb0f93cSkardel #else 137abb0f93cSkardel /* fill in for old/other timestamp interfaces */ 138abb0f93cSkardel #endif 139abb0f93cSkardel 140abb0f93cSkardel #if defined(SYS_WINNT) 141b3d6264cSchristos #include "win32_io.h" 142abb0f93cSkardel #include <isc/win32os.h> 143b3d6264cSchristos #endif 144abb0f93cSkardel 145abb0f93cSkardel /* 146abb0f93cSkardel * We do asynchronous input using the SIGIO facility. A number of 147abb0f93cSkardel * recvbuf buffers are preallocated for input. In the signal 148abb0f93cSkardel * handler we poll to see which sockets are ready and read the 149abb0f93cSkardel * packets from them into the recvbuf's along with a time stamp and 150abb0f93cSkardel * an indication of the source host and the interface it was received 151abb0f93cSkardel * through. This allows us to get as accurate receive time stamps 152abb0f93cSkardel * as possible independent of other processing going on. 153abb0f93cSkardel * 154abb0f93cSkardel * We watch the number of recvbufs available to the signal handler 155abb0f93cSkardel * and allocate more when this number drops below the low water 156abb0f93cSkardel * mark. If the signal handler should run out of buffers in the 157abb0f93cSkardel * interim it will drop incoming frames, the idea being that it is 158abb0f93cSkardel * better to drop a packet than to be inaccurate. 159abb0f93cSkardel */ 160abb0f93cSkardel 161abb0f93cSkardel 162abb0f93cSkardel /* 163abb0f93cSkardel * Other statistics of possible interest 164abb0f93cSkardel */ 165abb0f93cSkardel volatile u_long packets_dropped; /* total number of packets dropped on reception */ 166abb0f93cSkardel volatile u_long packets_ignored; /* packets received on wild card interface */ 167abb0f93cSkardel volatile u_long packets_received; /* total number of packets received */ 168abb0f93cSkardel u_long packets_sent; /* total number of packets sent */ 169abb0f93cSkardel u_long packets_notsent; /* total number of packets which couldn't be sent */ 170abb0f93cSkardel 171abb0f93cSkardel volatile u_long handler_calls; /* number of calls to interrupt handler */ 172abb0f93cSkardel volatile u_long handler_pkts; /* number of pkts received by handler */ 173abb0f93cSkardel u_long io_timereset; /* time counters were reset */ 174abb0f93cSkardel 175abb0f93cSkardel /* 176abb0f93cSkardel * Interface stuff 177abb0f93cSkardel */ 17845530cf1Skardel endpt * any_interface; /* wildcard ipv4 interface */ 17945530cf1Skardel endpt * any6_interface; /* wildcard ipv6 interface */ 18045530cf1Skardel endpt * loopback_interface; /* loopback ipv4 interface */ 181abb0f93cSkardel 182abb0f93cSkardel isc_boolean_t broadcast_client_enabled; /* is broadcast client enabled */ 183b3d6264cSchristos u_int sys_ifnum; /* next .ifnum to assign */ 184abb0f93cSkardel int ninterfaces; /* Total number of interfaces */ 185abb0f93cSkardel 186abb0f93cSkardel int disable_dynamic_updates; /* scan interfaces once only */ 187abb0f93cSkardel 188abb0f93cSkardel #ifdef REFCLOCK 189abb0f93cSkardel /* 190abb0f93cSkardel * Refclock stuff. We keep a chain of structures with data concerning 191abb0f93cSkardel * the guys we are doing I/O for. 192abb0f93cSkardel */ 193abb0f93cSkardel static struct refclockio *refio; 194abb0f93cSkardel #endif /* REFCLOCK */ 195abb0f93cSkardel 196abb0f93cSkardel /* 197abb0f93cSkardel * File descriptor masks etc. for call to select 198b3d6264cSchristos * Not needed for I/O Completion Ports or anything outside this file 199abb0f93cSkardel */ 200b3d6264cSchristos static fd_set activefds; 201b3d6264cSchristos static int maxactivefd; 202b3d6264cSchristos 203abb0f93cSkardel /* 204abb0f93cSkardel * bit alternating value to detect verified interfaces during an update cycle 205abb0f93cSkardel */ 206abb0f93cSkardel static u_short sys_interphase = 0; 207abb0f93cSkardel 20845530cf1Skardel static endpt * new_interface(endpt *); 20945530cf1Skardel static void add_interface(endpt *); 21045530cf1Skardel static int update_interfaces(u_short, interface_receiver_t, 21145530cf1Skardel void *); 21245530cf1Skardel static void remove_interface(endpt *); 21345530cf1Skardel static endpt * create_interface(u_short, endpt *); 214abb0f93cSkardel 21545530cf1Skardel static int is_wildcard_addr (const sockaddr_u *); 216abb0f93cSkardel 217abb0f93cSkardel /* 218abb0f93cSkardel * Multicast functions 219abb0f93cSkardel */ 220abb0f93cSkardel static isc_boolean_t addr_ismulticast (sockaddr_u *); 22145530cf1Skardel static isc_boolean_t is_anycast (sockaddr_u *, 22245530cf1Skardel const char *); 22345530cf1Skardel 224abb0f93cSkardel /* 225abb0f93cSkardel * Not all platforms support multicast 226abb0f93cSkardel */ 227abb0f93cSkardel #ifdef MCAST 22845530cf1Skardel static isc_boolean_t socket_multicast_enable (endpt *, sockaddr_u *); 22945530cf1Skardel static isc_boolean_t socket_multicast_disable(endpt *, sockaddr_u *); 230abb0f93cSkardel #endif 231abb0f93cSkardel 232abb0f93cSkardel #ifdef DEBUG 23345530cf1Skardel static void interface_dump (const endpt *); 23445530cf1Skardel static void sockaddr_dump (const sockaddr_u *); 235f40817b7Skardel static void print_interface (const endpt *, const char *, const char *); 236abb0f93cSkardel #define DPRINT_INTERFACE(level, args) do { if (debug >= (level)) { print_interface args; } } while (0) 237abb0f93cSkardel #else 238abb0f93cSkardel #define DPRINT_INTERFACE(level, args) do {} while (0) 239abb0f93cSkardel #endif 240abb0f93cSkardel 241abb0f93cSkardel typedef struct vsock vsock_t; 242abb0f93cSkardel enum desc_type { FD_TYPE_SOCKET, FD_TYPE_FILE }; 243abb0f93cSkardel 244abb0f93cSkardel struct vsock { 245abb0f93cSkardel vsock_t * link; 246abb0f93cSkardel SOCKET fd; 247abb0f93cSkardel enum desc_type type; 248abb0f93cSkardel }; 249abb0f93cSkardel 250abb0f93cSkardel vsock_t *fd_list; 251abb0f93cSkardel 252abb0f93cSkardel #if !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) 253abb0f93cSkardel /* 254abb0f93cSkardel * async notification processing (e. g. routing sockets) 255abb0f93cSkardel */ 256abb0f93cSkardel /* 257abb0f93cSkardel * support for receiving data on fd that is not a refclock or a socket 258abb0f93cSkardel * like e. g. routing sockets 259abb0f93cSkardel */ 260abb0f93cSkardel struct asyncio_reader { 261abb0f93cSkardel struct asyncio_reader *link; /* the list this is being kept in */ 262abb0f93cSkardel SOCKET fd; /* fd to be read */ 263abb0f93cSkardel void *data; /* possibly local data */ 264abb0f93cSkardel void (*receiver)(struct asyncio_reader *); /* input handler */ 265abb0f93cSkardel }; 266abb0f93cSkardel 267abb0f93cSkardel struct asyncio_reader *asyncio_reader_list; 268abb0f93cSkardel 269abb0f93cSkardel static void delete_asyncio_reader (struct asyncio_reader *); 270abb0f93cSkardel static struct asyncio_reader *new_asyncio_reader (void); 271abb0f93cSkardel static void add_asyncio_reader (struct asyncio_reader *, enum desc_type); 272abb0f93cSkardel static void remove_asyncio_reader (struct asyncio_reader *); 273abb0f93cSkardel 274abb0f93cSkardel #endif /* !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) */ 275abb0f93cSkardel 276abb0f93cSkardel static void init_async_notifications (void); 277abb0f93cSkardel 27845530cf1Skardel static int addr_eqprefix (const sockaddr_u *, const sockaddr_u *, 27945530cf1Skardel int); 28045530cf1Skardel static int addr_samesubnet (const sockaddr_u *, const sockaddr_u *, 28145530cf1Skardel const sockaddr_u *, const sockaddr_u *); 282abb0f93cSkardel static int create_sockets (u_short); 28345530cf1Skardel static SOCKET open_socket (sockaddr_u *, int, int, endpt *); 284abb0f93cSkardel static void set_reuseaddr (int); 285abb0f93cSkardel static isc_boolean_t socket_broadcast_enable (struct interface *, SOCKET, sockaddr_u *); 286335f7552Schristos 287335f7552Schristos #if !defined(HAVE_IO_COMPLETION_PORT) && !defined(HAVE_SIGNALED_IO) 288335f7552Schristos static char * fdbits (int, const fd_set *); 289335f7552Schristos #endif 290ad131110Schristos #ifdef OS_MISSES_SPECIFIC_ROUTE_UPDATES 291abb0f93cSkardel static isc_boolean_t socket_broadcast_disable (struct interface *, sockaddr_u *); 292ad131110Schristos #endif 293abb0f93cSkardel 294abb0f93cSkardel typedef struct remaddr remaddr_t; 295abb0f93cSkardel 296abb0f93cSkardel struct remaddr { 297abb0f93cSkardel remaddr_t * link; 298abb0f93cSkardel sockaddr_u addr; 29945530cf1Skardel endpt * ep; 300abb0f93cSkardel }; 301abb0f93cSkardel 302abb0f93cSkardel remaddr_t * remoteaddr_list; 30345530cf1Skardel endpt * ep_list; /* complete endpt list */ 30445530cf1Skardel endpt * mc4_list; /* IPv4 mcast-capable unicast endpts */ 30545530cf1Skardel endpt * mc6_list; /* IPv6 mcast-capable unicast endpts */ 306abb0f93cSkardel 30745530cf1Skardel static endpt * wildipv4; 30845530cf1Skardel static endpt * wildipv6; 309abb0f93cSkardel 310b3d6264cSchristos #ifdef SYS_WINNT 311b3d6264cSchristos int accept_wildcard_if_for_winnt; 312b3d6264cSchristos #else 313b3d6264cSchristos const int accept_wildcard_if_for_winnt = FALSE; 314b3d6264cSchristos #endif 315b3d6264cSchristos 31645530cf1Skardel static void add_fd_to_list (SOCKET, enum desc_type); 31745530cf1Skardel static endpt * find_addr_in_list (sockaddr_u *); 31845530cf1Skardel static endpt * find_flagged_addr_in_list(sockaddr_u *, u_int32); 319abb0f93cSkardel static void delete_addr_from_list (sockaddr_u *); 32045530cf1Skardel static void delete_interface_from_list(endpt *); 321abb0f93cSkardel static void close_and_delete_fd_from_list(SOCKET); 32245530cf1Skardel static void add_addr_to_list (sockaddr_u *, endpt *); 323abb0f93cSkardel static void create_wildcards (u_short); 32445530cf1Skardel static endpt * findlocalinterface (sockaddr_u *, int, int); 32545530cf1Skardel static endpt * findclosestinterface (sockaddr_u *, int); 326abb0f93cSkardel #ifdef DEBUG 327abb0f93cSkardel static const char * action_text (nic_rule_action); 328abb0f93cSkardel #endif 32945530cf1Skardel static nic_rule_action interface_action(char *, sockaddr_u *, u_int32); 330abb0f93cSkardel static void convert_isc_if (isc_interface_t *, 33145530cf1Skardel endpt *, u_short); 33245530cf1Skardel static void calc_addr_distance(sockaddr_u *, 33345530cf1Skardel const sockaddr_u *, 33445530cf1Skardel const sockaddr_u *); 33545530cf1Skardel static int cmp_addr_distance(const sockaddr_u *, 33645530cf1Skardel const sockaddr_u *); 337abb0f93cSkardel 338abb0f93cSkardel /* 339abb0f93cSkardel * Routines to read the ntp packets 340abb0f93cSkardel */ 341abb0f93cSkardel #if !defined(HAVE_IO_COMPLETION_PORT) 342abb0f93cSkardel static inline int read_network_packet (SOCKET, struct interface *, l_fp); 343b3d6264cSchristos static void ntpd_addremove_io_fd (int, int, int); 344335f7552Schristos static void input_handler_scan (const l_fp*, const fd_set*); 345335f7552Schristos static int/*BOOL*/ sanitize_fdset (int errc); 346b3d6264cSchristos #ifdef REFCLOCK 347abb0f93cSkardel static inline int read_refclock_packet (SOCKET, struct refclockio *, l_fp); 348abb0f93cSkardel #endif 349335f7552Schristos #ifdef HAVE_SIGNALED_IO 350335f7552Schristos static void input_handler (l_fp*); 351b3d6264cSchristos #endif 352335f7552Schristos #endif 353abb0f93cSkardel 354b3d6264cSchristos 355b3d6264cSchristos #ifndef HAVE_IO_COMPLETION_PORT 356abb0f93cSkardel void 357b3d6264cSchristos maintain_activefds( 358b3d6264cSchristos int fd, 359b3d6264cSchristos int closing 360abb0f93cSkardel ) 361abb0f93cSkardel { 362b3d6264cSchristos int i; 363abb0f93cSkardel 364b3d6264cSchristos if (fd < 0 || fd >= FD_SETSIZE) { 365abb0f93cSkardel msyslog(LOG_ERR, 366b3d6264cSchristos "Too many sockets in use, FD_SETSIZE %d exceeded by fd %d", 367b3d6264cSchristos FD_SETSIZE, fd); 368b3d6264cSchristos exit(1); 369abb0f93cSkardel } 370abb0f93cSkardel 371b3d6264cSchristos if (!closing) { 372b3d6264cSchristos FD_SET(fd, &activefds); 373b3d6264cSchristos maxactivefd = max(fd, maxactivefd); 374abb0f93cSkardel } else { 375b3d6264cSchristos FD_CLR(fd, &activefds); 376b3d6264cSchristos if (maxactivefd && fd == maxactivefd) { 377b3d6264cSchristos for (i = maxactivefd - 1; i >= 0; i--) 378b3d6264cSchristos if (FD_ISSET(i, &activefds)) { 379b3d6264cSchristos maxactivefd = i; 380b3d6264cSchristos break; 381abb0f93cSkardel } 38209f14f80Schristos INSIST(fd != maxactivefd); 383abb0f93cSkardel } 384b3d6264cSchristos } 385b3d6264cSchristos } 386b3d6264cSchristos #endif /* !HAVE_IO_COMPLETION_PORT */ 387b3d6264cSchristos 388abb0f93cSkardel 389abb0f93cSkardel #ifdef DEBUG_TIMING 390abb0f93cSkardel /* 391abb0f93cSkardel * collect timing information for various processing 392b3d6264cSchristos * paths. currently we only pass them on to the file 393abb0f93cSkardel * for later processing. this could also do histogram 394abb0f93cSkardel * based analysis in other to reduce the load (and skew) 395abb0f93cSkardel * dur to the file output 396abb0f93cSkardel */ 397abb0f93cSkardel void 398abb0f93cSkardel collect_timing(struct recvbuf *rb, const char *tag, int count, l_fp *dts) 399abb0f93cSkardel { 400abb0f93cSkardel char buf[256]; 401abb0f93cSkardel 402abb0f93cSkardel snprintf(buf, sizeof(buf), "%s %d %s %s", 403abb0f93cSkardel (rb != NULL) 404abb0f93cSkardel ? ((rb->dstadr != NULL) 405abb0f93cSkardel ? stoa(&rb->recv_srcadr) 406abb0f93cSkardel : "-REFCLOCK-") 407abb0f93cSkardel : "-", 408abb0f93cSkardel count, lfptoa(dts, 9), tag); 409abb0f93cSkardel record_timing_stats(buf); 410abb0f93cSkardel } 411abb0f93cSkardel #endif 412abb0f93cSkardel 413abb0f93cSkardel /* 414abb0f93cSkardel * About dynamic interfaces, sockets, reception and more... 415abb0f93cSkardel * 416abb0f93cSkardel * the code solves following tasks: 417abb0f93cSkardel * 418abb0f93cSkardel * - keep a current list of active interfaces in order 419abb0f93cSkardel * to bind to to the interface address on NTP_PORT so that 420abb0f93cSkardel * all wild and specific bindings for NTP_PORT are taken by ntpd 421abb0f93cSkardel * to avoid other daemons messing with the time or sockets. 422abb0f93cSkardel * - all interfaces keep a list of peers that are referencing 423abb0f93cSkardel * the interface in order to quickly re-assign the peers to 424abb0f93cSkardel * new interface in case an interface is deleted (=> gone from system or 425abb0f93cSkardel * down) 426abb0f93cSkardel * - have a preconfigured socket ready with the right local address 427abb0f93cSkardel * for transmission and reception 428abb0f93cSkardel * - have an address list for all destination addresses used within ntpd 429abb0f93cSkardel * to find the "right" preconfigured socket. 430abb0f93cSkardel * - facilitate updating the internal interface list with respect to 431abb0f93cSkardel * the current kernel state 432abb0f93cSkardel * 433abb0f93cSkardel * special issues: 434abb0f93cSkardel * 435abb0f93cSkardel * - mapping of multicast addresses to the interface affected is not always 436abb0f93cSkardel * one to one - especially on hosts with multiple interfaces 437abb0f93cSkardel * the code here currently allocates a separate interface entry for those 438abb0f93cSkardel * multicast addresses 439abb0f93cSkardel * iff it is able to bind to a *new* socket with the multicast address (flags |= MCASTIF) 440abb0f93cSkardel * in case of failure the multicast address is bound to an existing interface. 441abb0f93cSkardel * - on some systems it is perfectly legal to assign the same address to 442abb0f93cSkardel * multiple interfaces. Therefore this code does not keep a list of interfaces 443abb0f93cSkardel * but a list of interfaces that represent a unique address as determined by the kernel 444abb0f93cSkardel * by the procedure in findlocalinterface. Thus it is perfectly legal to see only 445abb0f93cSkardel * one representative of a group of real interfaces if they share the same address. 446abb0f93cSkardel * 447abb0f93cSkardel * Frank Kardel 20050910 448abb0f93cSkardel */ 449abb0f93cSkardel 450abb0f93cSkardel /* 451b3d6264cSchristos * init_io - initialize I/O module. 452abb0f93cSkardel */ 453abb0f93cSkardel void 454abb0f93cSkardel init_io(void) 455abb0f93cSkardel { 456b3d6264cSchristos /* Init buffer free list and stat counters */ 457abb0f93cSkardel init_recvbuff(RECV_INIT); 458b3d6264cSchristos /* update interface every 5 minutes as default */ 459b3d6264cSchristos interface_interval = 300; 460b3d6264cSchristos 461b3d6264cSchristos #ifdef WORK_PIPE 462b3d6264cSchristos addremove_io_fd = &ntpd_addremove_io_fd; 463b3d6264cSchristos #endif 464abb0f93cSkardel 465335f7552Schristos #if defined(SYS_WINNT) 466abb0f93cSkardel init_io_completion_port(); 467335f7552Schristos #elif defined(HAVE_SIGNALED_IO) 468b3d6264cSchristos (void) set_signal(input_handler); 469abb0f93cSkardel #endif 470abb0f93cSkardel } 471abb0f93cSkardel 472abb0f93cSkardel 473b3d6264cSchristos static void 474b3d6264cSchristos ntpd_addremove_io_fd( 475b3d6264cSchristos int fd, 476b3d6264cSchristos int is_pipe, 477b3d6264cSchristos int remove_it 478b3d6264cSchristos ) 479b3d6264cSchristos { 480b3d6264cSchristos UNUSED_ARG(is_pipe); 481b3d6264cSchristos 482b3d6264cSchristos #ifdef HAVE_SIGNALED_IO 483335f7552Schristos if (!remove_it) 484b3d6264cSchristos init_socket_sig(fd); 485b3d6264cSchristos #endif /* not HAVE_SIGNALED_IO */ 486b3d6264cSchristos 487b3d6264cSchristos maintain_activefds(fd, remove_it); 488b3d6264cSchristos } 489b3d6264cSchristos 490b3d6264cSchristos 491abb0f93cSkardel /* 492abb0f93cSkardel * io_open_sockets - call socket creation routine 493abb0f93cSkardel */ 494abb0f93cSkardel void 495abb0f93cSkardel io_open_sockets(void) 496abb0f93cSkardel { 497abb0f93cSkardel static int already_opened; 498abb0f93cSkardel 499abb0f93cSkardel if (already_opened || HAVE_OPT( SAVECONFIGQUIT )) 500abb0f93cSkardel return; 501abb0f93cSkardel 502abb0f93cSkardel already_opened = 1; 503abb0f93cSkardel 504abb0f93cSkardel /* 505abb0f93cSkardel * Create the sockets 506abb0f93cSkardel */ 507abb0f93cSkardel BLOCKIO(); 508abb0f93cSkardel create_sockets(NTP_PORT); 509abb0f93cSkardel UNBLOCKIO(); 510abb0f93cSkardel 511abb0f93cSkardel init_async_notifications(); 512abb0f93cSkardel 513abb0f93cSkardel DPRINTF(3, ("io_open_sockets: maxactivefd %d\n", maxactivefd)); 514abb0f93cSkardel } 515abb0f93cSkardel 516abb0f93cSkardel 517abb0f93cSkardel #ifdef DEBUG 518abb0f93cSkardel /* 519abb0f93cSkardel * function to dump the contents of the interface structure 520abb0f93cSkardel * for debugging use only. 521*1c24ec91Schristos * We face a dilemma here -- sockets are FDs under POSIX and 522*1c24ec91Schristos * actually HANDLES under Windows. So we use '%lld' as format 523*1c24ec91Schristos * and cast the value to 'long long'; this should not hurt 524*1c24ec91Schristos * with UNIX-like systems and does not truncate values on Win64. 525abb0f93cSkardel */ 526abb0f93cSkardel void 52745530cf1Skardel interface_dump(const endpt *itf) 528abb0f93cSkardel { 529abb0f93cSkardel printf("Dumping interface: %p\n", itf); 530*1c24ec91Schristos printf("fd = %lld\n", (long long)itf->fd); 531*1c24ec91Schristos printf("bfd = %lld\n", (long long)itf->bfd); 532abb0f93cSkardel printf("sin = %s,\n", stoa(&itf->sin)); 533abb0f93cSkardel sockaddr_dump(&itf->sin); 534abb0f93cSkardel printf("bcast = %s,\n", stoa(&itf->bcast)); 535abb0f93cSkardel sockaddr_dump(&itf->bcast); 536abb0f93cSkardel printf("mask = %s,\n", stoa(&itf->mask)); 537abb0f93cSkardel sockaddr_dump(&itf->mask); 538abb0f93cSkardel printf("name = %s\n", itf->name); 539abb0f93cSkardel printf("flags = 0x%08x\n", itf->flags); 540abb0f93cSkardel printf("last_ttl = %d\n", itf->last_ttl); 541abb0f93cSkardel printf("addr_refid = %08x\n", itf->addr_refid); 542abb0f93cSkardel printf("num_mcast = %d\n", itf->num_mcast); 543abb0f93cSkardel printf("received = %ld\n", itf->received); 544abb0f93cSkardel printf("sent = %ld\n", itf->sent); 545abb0f93cSkardel printf("notsent = %ld\n", itf->notsent); 54645530cf1Skardel printf("ifindex = %u\n", itf->ifindex); 547abb0f93cSkardel printf("peercnt = %u\n", itf->peercnt); 548abb0f93cSkardel printf("phase = %u\n", itf->phase); 549abb0f93cSkardel } 550abb0f93cSkardel 551abb0f93cSkardel /* 552abb0f93cSkardel * sockaddr_dump - hex dump the start of a sockaddr_u 553abb0f93cSkardel */ 554abb0f93cSkardel static void 55545530cf1Skardel sockaddr_dump(const sockaddr_u *psau) 556abb0f93cSkardel { 557b3d6264cSchristos /* Limit the size of the sockaddr_in6 hex dump */ 55845530cf1Skardel const int maxsize = min(32, sizeof(psau->sa6)); 55945530cf1Skardel const u_char * cp; 560abb0f93cSkardel int i; 561abb0f93cSkardel 562b3d6264cSchristos /* XXX: Should we limit maxsize based on psau->saX.sin_family? */ 563b3d6264cSchristos cp = (const void *)&psau->sa6; 564abb0f93cSkardel 56545530cf1Skardel for(i = 0; i < maxsize; i++) { 566abb0f93cSkardel printf("%02x", *cp++); 567abb0f93cSkardel if (!((i + 1) % 4)) 568abb0f93cSkardel printf(" "); 569abb0f93cSkardel } 570abb0f93cSkardel printf("\n"); 571abb0f93cSkardel } 572abb0f93cSkardel 573abb0f93cSkardel /* 574abb0f93cSkardel * print_interface - helper to output debug information 575abb0f93cSkardel */ 576abb0f93cSkardel static void 577f40817b7Skardel print_interface(const endpt *iface, const char *pfx, const char *sfx) 578abb0f93cSkardel { 579*1c24ec91Schristos printf("%sinterface #%d: fd=%lld, bfd=%lld, name=%s, flags=0x%x, ifindex=%u, sin=%s", 580abb0f93cSkardel pfx, 581abb0f93cSkardel iface->ifnum, 582*1c24ec91Schristos (long long)iface->fd, 583*1c24ec91Schristos (long long)iface->bfd, 584abb0f93cSkardel iface->name, 585abb0f93cSkardel iface->flags, 58645530cf1Skardel iface->ifindex, 587abb0f93cSkardel stoa(&iface->sin)); 588abb0f93cSkardel if (AF_INET == iface->family) { 589abb0f93cSkardel if (iface->flags & INT_BROADCAST) 590abb0f93cSkardel printf(", bcast=%s", stoa(&iface->bcast)); 591abb0f93cSkardel printf(", mask=%s", stoa(&iface->mask)); 592abb0f93cSkardel } 593abb0f93cSkardel printf(", %s:%s", 594abb0f93cSkardel (iface->ignore_packets) 595abb0f93cSkardel ? "Disabled" 596abb0f93cSkardel : "Enabled", 597abb0f93cSkardel sfx); 598abb0f93cSkardel if (debug > 4) /* in-depth debugging only */ 599abb0f93cSkardel interface_dump(iface); 600abb0f93cSkardel } 601abb0f93cSkardel #endif 602abb0f93cSkardel 603abb0f93cSkardel #if !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) 604abb0f93cSkardel /* 605abb0f93cSkardel * create an asyncio_reader structure 606abb0f93cSkardel */ 607abb0f93cSkardel static struct asyncio_reader * 608abb0f93cSkardel new_asyncio_reader(void) 609abb0f93cSkardel { 610abb0f93cSkardel struct asyncio_reader *reader; 611abb0f93cSkardel 612b3d6264cSchristos reader = emalloc_zero(sizeof(*reader)); 613abb0f93cSkardel reader->fd = INVALID_SOCKET; 614b3d6264cSchristos 615abb0f93cSkardel return reader; 616abb0f93cSkardel } 617abb0f93cSkardel 618abb0f93cSkardel /* 619abb0f93cSkardel * delete a reader 620abb0f93cSkardel */ 621abb0f93cSkardel static void 622abb0f93cSkardel delete_asyncio_reader( 623abb0f93cSkardel struct asyncio_reader *reader 624abb0f93cSkardel ) 625abb0f93cSkardel { 626abb0f93cSkardel free(reader); 627abb0f93cSkardel } 628abb0f93cSkardel 629abb0f93cSkardel /* 630abb0f93cSkardel * add asynchio_reader 631abb0f93cSkardel */ 632abb0f93cSkardel static void 633abb0f93cSkardel add_asyncio_reader( 634abb0f93cSkardel struct asyncio_reader * reader, 635abb0f93cSkardel enum desc_type type) 636abb0f93cSkardel { 637abb0f93cSkardel LINK_SLIST(asyncio_reader_list, reader, link); 638abb0f93cSkardel add_fd_to_list(reader->fd, type); 639abb0f93cSkardel } 640abb0f93cSkardel 641abb0f93cSkardel /* 642abb0f93cSkardel * remove asynchio_reader 643abb0f93cSkardel */ 644abb0f93cSkardel static void 645abb0f93cSkardel remove_asyncio_reader( 646abb0f93cSkardel struct asyncio_reader *reader 647abb0f93cSkardel ) 648abb0f93cSkardel { 649abb0f93cSkardel struct asyncio_reader *unlinked; 650abb0f93cSkardel 651abb0f93cSkardel UNLINK_SLIST(unlinked, asyncio_reader_list, reader, link, 652abb0f93cSkardel struct asyncio_reader); 653abb0f93cSkardel 654abb0f93cSkardel if (reader->fd != INVALID_SOCKET) 655abb0f93cSkardel close_and_delete_fd_from_list(reader->fd); 656abb0f93cSkardel 657abb0f93cSkardel reader->fd = INVALID_SOCKET; 658abb0f93cSkardel } 659abb0f93cSkardel #endif /* !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) */ 660abb0f93cSkardel 66145530cf1Skardel 66245530cf1Skardel /* compare two sockaddr prefixes */ 66345530cf1Skardel static int 66445530cf1Skardel addr_eqprefix( 66545530cf1Skardel const sockaddr_u * a, 66645530cf1Skardel const sockaddr_u * b, 66745530cf1Skardel int prefixlen 66845530cf1Skardel ) 66945530cf1Skardel { 67045530cf1Skardel isc_netaddr_t isc_a; 67145530cf1Skardel isc_netaddr_t isc_b; 67245530cf1Skardel isc_sockaddr_t isc_sa; 67345530cf1Skardel 674b3d6264cSchristos ZERO(isc_sa); 675b3d6264cSchristos memcpy(&isc_sa.type, a, min(sizeof(isc_sa.type), sizeof(*a))); 67645530cf1Skardel isc_netaddr_fromsockaddr(&isc_a, &isc_sa); 67745530cf1Skardel 678b3d6264cSchristos ZERO(isc_sa); 679b3d6264cSchristos memcpy(&isc_sa.type, b, min(sizeof(isc_sa.type), sizeof(*b))); 68045530cf1Skardel isc_netaddr_fromsockaddr(&isc_b, &isc_sa); 68145530cf1Skardel 68245530cf1Skardel return (int)isc_netaddr_eqprefix(&isc_a, &isc_b, 68345530cf1Skardel (u_int)prefixlen); 68445530cf1Skardel } 68545530cf1Skardel 68645530cf1Skardel 68745530cf1Skardel static int 68845530cf1Skardel addr_samesubnet( 68945530cf1Skardel const sockaddr_u * a, 69045530cf1Skardel const sockaddr_u * a_mask, 69145530cf1Skardel const sockaddr_u * b, 69245530cf1Skardel const sockaddr_u * b_mask 69345530cf1Skardel ) 69445530cf1Skardel { 69545530cf1Skardel const u_int32 * pa; 69645530cf1Skardel const u_int32 * pa_limit; 69745530cf1Skardel const u_int32 * pb; 69845530cf1Skardel const u_int32 * pm; 69945530cf1Skardel size_t loops; 70045530cf1Skardel 70109f14f80Schristos REQUIRE(AF(a) == AF(a_mask)); 70209f14f80Schristos REQUIRE(AF(b) == AF(b_mask)); 70345530cf1Skardel /* 70445530cf1Skardel * With address and mask families verified to match, comparing 70545530cf1Skardel * the masks also validates the address's families match. 70645530cf1Skardel */ 70745530cf1Skardel if (!SOCK_EQ(a_mask, b_mask)) 70845530cf1Skardel return FALSE; 70945530cf1Skardel 71045530cf1Skardel if (IS_IPV6(a)) { 71145530cf1Skardel loops = sizeof(NSRCADR6(a)) / sizeof(*pa); 71245530cf1Skardel pa = (const void *)&NSRCADR6(a); 71345530cf1Skardel pb = (const void *)&NSRCADR6(b); 71445530cf1Skardel pm = (const void *)&NSRCADR6(a_mask); 71545530cf1Skardel } else { 71645530cf1Skardel loops = sizeof(NSRCADR(a)) / sizeof(*pa); 71745530cf1Skardel pa = (const void *)&NSRCADR(a); 71845530cf1Skardel pb = (const void *)&NSRCADR(b); 71945530cf1Skardel pm = (const void *)&NSRCADR(a_mask); 72045530cf1Skardel } 72145530cf1Skardel for (pa_limit = pa + loops; pa < pa_limit; pa++, pb++, pm++) 72245530cf1Skardel if ((*pa & *pm) != (*pb & *pm)) 72345530cf1Skardel return FALSE; 72445530cf1Skardel 72545530cf1Skardel return TRUE; 72645530cf1Skardel } 72745530cf1Skardel 72845530cf1Skardel 729abb0f93cSkardel /* 730abb0f93cSkardel * interface list enumerator - visitor pattern 731abb0f93cSkardel */ 732abb0f93cSkardel void 733abb0f93cSkardel interface_enumerate( 734abb0f93cSkardel interface_receiver_t receiver, 735abb0f93cSkardel void * data 736abb0f93cSkardel ) 737abb0f93cSkardel { 738abb0f93cSkardel interface_info_t ifi; 739abb0f93cSkardel 740abb0f93cSkardel ifi.action = IFS_EXISTS; 74145530cf1Skardel for (ifi.ep = ep_list; ifi.ep != NULL; ifi.ep = ifi.ep->elink) 742abb0f93cSkardel (*receiver)(data, &ifi); 743abb0f93cSkardel } 744abb0f93cSkardel 745abb0f93cSkardel /* 746abb0f93cSkardel * do standard initialization of interface structure 747abb0f93cSkardel */ 748abb0f93cSkardel static void 749abb0f93cSkardel init_interface( 75045530cf1Skardel endpt *ep 751abb0f93cSkardel ) 752abb0f93cSkardel { 753b3d6264cSchristos ZERO(*ep); 75445530cf1Skardel ep->fd = INVALID_SOCKET; 75545530cf1Skardel ep->bfd = INVALID_SOCKET; 75645530cf1Skardel ep->phase = sys_interphase; 757abb0f93cSkardel } 758abb0f93cSkardel 759abb0f93cSkardel 760abb0f93cSkardel /* 761abb0f93cSkardel * create new interface structure initialize from 762abb0f93cSkardel * template structure or via standard initialization 763abb0f93cSkardel * function 764abb0f93cSkardel */ 765abb0f93cSkardel static struct interface * 766abb0f93cSkardel new_interface( 767abb0f93cSkardel struct interface *interface 768abb0f93cSkardel ) 769abb0f93cSkardel { 770abb0f93cSkardel struct interface * iface; 771abb0f93cSkardel 772abb0f93cSkardel iface = emalloc(sizeof(*iface)); 773abb0f93cSkardel 774abb0f93cSkardel if (NULL == interface) 775abb0f93cSkardel init_interface(iface); 776abb0f93cSkardel else /* use the template */ 777abb0f93cSkardel memcpy(iface, interface, sizeof(*iface)); 778abb0f93cSkardel 779abb0f93cSkardel /* count every new instance of an interface in the system */ 780abb0f93cSkardel iface->ifnum = sys_ifnum++; 781abb0f93cSkardel iface->starttime = current_time; 782abb0f93cSkardel 783335f7552Schristos # ifdef HAVE_IO_COMPLETION_PORT 784335f7552Schristos if (!io_completion_port_add_interface(iface)) { 785335f7552Schristos msyslog(LOG_EMERG, "cannot register interface with IO engine -- will exit now"); 786335f7552Schristos exit(1); 787335f7552Schristos } 788335f7552Schristos # endif 789abb0f93cSkardel return iface; 790abb0f93cSkardel } 791abb0f93cSkardel 792abb0f93cSkardel 793abb0f93cSkardel /* 794abb0f93cSkardel * return interface storage into free memory pool 795abb0f93cSkardel */ 796335f7552Schristos static void 797abb0f93cSkardel delete_interface( 79845530cf1Skardel endpt *ep 799abb0f93cSkardel ) 800abb0f93cSkardel { 801335f7552Schristos # ifdef HAVE_IO_COMPLETION_PORT 802335f7552Schristos io_completion_port_remove_interface(ep); 803335f7552Schristos # endif 80445530cf1Skardel free(ep); 805abb0f93cSkardel } 806abb0f93cSkardel 807abb0f93cSkardel 808abb0f93cSkardel /* 809abb0f93cSkardel * link interface into list of known interfaces 810abb0f93cSkardel */ 811abb0f93cSkardel static void 812abb0f93cSkardel add_interface( 81345530cf1Skardel endpt * ep 814abb0f93cSkardel ) 815abb0f93cSkardel { 81645530cf1Skardel endpt ** pmclisthead; 81745530cf1Skardel endpt * scan; 81845530cf1Skardel endpt * scan_next; 81945530cf1Skardel endpt * unlinked; 82045530cf1Skardel sockaddr_u * addr; 82145530cf1Skardel int ep_local; 82245530cf1Skardel int scan_local; 82345530cf1Skardel int same_subnet; 82445530cf1Skardel int ep_univ_iid; /* iface ID from MAC address */ 82545530cf1Skardel int scan_univ_iid; /* see RFC 4291 */ 82645530cf1Skardel int ep_privacy; /* random local iface ID */ 82745530cf1Skardel int scan_privacy; /* see RFC 4941 */ 82845530cf1Skardel int rc; 82945530cf1Skardel 830b3d6264cSchristos /* Calculate the refid */ 83145530cf1Skardel ep->addr_refid = addr2refid(&ep->sin); 832b3d6264cSchristos /* link at tail so ntpdc -c ifstats index increases each row */ 833b3d6264cSchristos LINK_TAIL_SLIST(ep_list, ep, elink, endpt); 834abb0f93cSkardel ninterfaces++; 83545530cf1Skardel #ifdef MCAST 83645530cf1Skardel /* the rest is for enabled multicast-capable addresses only */ 83745530cf1Skardel if (ep->ignore_packets || !(INT_MULTICAST & ep->flags) || 83845530cf1Skardel INT_LOOPBACK & ep->flags) 83945530cf1Skardel return; 84045530cf1Skardel # ifndef INCLUDE_IPV6_MULTICAST_SUPPORT 84145530cf1Skardel if (AF_INET6 == ep->family) 84245530cf1Skardel return; 84345530cf1Skardel # endif 84445530cf1Skardel pmclisthead = (AF_INET == ep->family) 84545530cf1Skardel ? &mc4_list 84645530cf1Skardel : &mc6_list; 84745530cf1Skardel 84845530cf1Skardel if (AF_INET6 == ep->family) { 84945530cf1Skardel ep_local = 85045530cf1Skardel IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(&ep->sin)) || 85145530cf1Skardel IN6_IS_ADDR_SITELOCAL(PSOCK_ADDR6(&ep->sin)); 85245530cf1Skardel ep_univ_iid = IS_IID_UNIV(&ep->sin); 85345530cf1Skardel ep_privacy = !!(INT_PRIVACY & ep->flags); 85445530cf1Skardel } else { 85545530cf1Skardel ep_local = FALSE; 85645530cf1Skardel ep_univ_iid = FALSE; 85745530cf1Skardel ep_privacy = FALSE; 85845530cf1Skardel } 85945530cf1Skardel DPRINTF(4, ("add_interface mcast-capable %s%s%s%s\n", 86045530cf1Skardel stoa(&ep->sin), 86145530cf1Skardel (ep_local) ? " link/scope-local" : "", 86245530cf1Skardel (ep_univ_iid) ? " univ-IID" : "", 86345530cf1Skardel (ep_privacy) ? " privacy" : "")); 86445530cf1Skardel /* 86545530cf1Skardel * If we have multiple local addresses on the same network 86645530cf1Skardel * interface, and some are link- or site-local, do not multicast 86745530cf1Skardel * out from the link-/site-local addresses by default, to avoid 86845530cf1Skardel * duplicate manycastclient associations between v6 peers using 86945530cf1Skardel * link-local and global addresses. link-local can still be 87045530cf1Skardel * chosen using "nic ignore myv6globalprefix::/64". 87145530cf1Skardel * Similarly, if we have multiple global addresses from the same 87245530cf1Skardel * prefix on the same network interface, multicast from one, 87345530cf1Skardel * preferring EUI-64, then static, then least RFC 4941 privacy 87445530cf1Skardel * addresses. 87545530cf1Skardel */ 87645530cf1Skardel for (scan = *pmclisthead; scan != NULL; scan = scan_next) { 87745530cf1Skardel scan_next = scan->mclink; 87845530cf1Skardel if (ep->family != scan->family) 87945530cf1Skardel continue; 88045530cf1Skardel if (strcmp(ep->name, scan->name)) 88145530cf1Skardel continue; 88245530cf1Skardel same_subnet = addr_samesubnet(&ep->sin, &ep->mask, 88345530cf1Skardel &scan->sin, &scan->mask); 88445530cf1Skardel if (AF_INET6 == ep->family) { 88545530cf1Skardel addr = &scan->sin; 88645530cf1Skardel scan_local = 88745530cf1Skardel IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(addr)) || 88845530cf1Skardel IN6_IS_ADDR_SITELOCAL(PSOCK_ADDR6(addr)); 88945530cf1Skardel scan_univ_iid = IS_IID_UNIV(addr); 89045530cf1Skardel scan_privacy = !!(INT_PRIVACY & scan->flags); 89145530cf1Skardel } else { 89245530cf1Skardel scan_local = FALSE; 89345530cf1Skardel scan_univ_iid = FALSE; 89445530cf1Skardel scan_privacy = FALSE; 89545530cf1Skardel } 89645530cf1Skardel DPRINTF(4, ("add_interface mcast-capable scan %s%s%s%s\n", 89745530cf1Skardel stoa(&scan->sin), 89845530cf1Skardel (scan_local) ? " link/scope-local" : "", 89945530cf1Skardel (scan_univ_iid) ? " univ-IID" : "", 90045530cf1Skardel (scan_privacy) ? " privacy" : "")); 90145530cf1Skardel if ((ep_local && !scan_local) || (same_subnet && 90245530cf1Skardel ((ep_privacy && !scan_privacy) || 90345530cf1Skardel (!ep_univ_iid && scan_univ_iid)))) { 90445530cf1Skardel DPRINTF(4, ("did not add %s to %s of IPv6 multicast-capable list which already has %s\n", 90545530cf1Skardel stoa(&ep->sin), 90645530cf1Skardel (ep_local) 90745530cf1Skardel ? "tail" 90845530cf1Skardel : "head", 90945530cf1Skardel stoa(&scan->sin))); 91045530cf1Skardel return; 91145530cf1Skardel } 91245530cf1Skardel if ((scan_local && !ep_local) || (same_subnet && 91345530cf1Skardel ((scan_privacy && !ep_privacy) || 91445530cf1Skardel (!scan_univ_iid && ep_univ_iid)))) { 91545530cf1Skardel UNLINK_SLIST(unlinked, *pmclisthead, 91645530cf1Skardel scan, mclink, endpt); 91745530cf1Skardel DPRINTF(4, ("%s %s from IPv6 multicast-capable list to add %s\n", 91845530cf1Skardel (unlinked != scan) 91945530cf1Skardel ? "Failed to remove" 92045530cf1Skardel : "removed", 92145530cf1Skardel stoa(&scan->sin), stoa(&ep->sin))); 92245530cf1Skardel } 92345530cf1Skardel } 92445530cf1Skardel /* 92545530cf1Skardel * Add link/site local at the tail of the multicast- 92645530cf1Skardel * capable unicast interfaces list, so that ntpd will 92745530cf1Skardel * send from global addresses before link-/site-local 92845530cf1Skardel * ones. 92945530cf1Skardel */ 93045530cf1Skardel if (ep_local) 93145530cf1Skardel LINK_TAIL_SLIST(*pmclisthead, ep, mclink, endpt); 93245530cf1Skardel else 93345530cf1Skardel LINK_SLIST(*pmclisthead, ep, mclink); 93445530cf1Skardel DPRINTF(4, ("added %s to %s of IPv%s multicast-capable unicast local address list\n", 93545530cf1Skardel stoa(&ep->sin), 93645530cf1Skardel (ep_local) 93745530cf1Skardel ? "tail" 93845530cf1Skardel : "head", 93945530cf1Skardel (AF_INET == ep->family) 94045530cf1Skardel ? "4" 94145530cf1Skardel : "6")); 94245530cf1Skardel 943b3d6264cSchristos if (INVALID_SOCKET == ep->fd) 944b3d6264cSchristos return; 945b3d6264cSchristos 94645530cf1Skardel /* 94745530cf1Skardel * select the local address from which to send to multicast. 94845530cf1Skardel */ 94945530cf1Skardel switch (AF(&ep->sin)) { 950b3d6264cSchristos 95145530cf1Skardel case AF_INET : 95245530cf1Skardel rc = setsockopt(ep->fd, IPPROTO_IP, 95345530cf1Skardel IP_MULTICAST_IF, 95445530cf1Skardel (void *)&NSRCADR(&ep->sin), 95545530cf1Skardel sizeof(NSRCADR(&ep->sin))); 95645530cf1Skardel if (rc) 95745530cf1Skardel msyslog(LOG_ERR, 95845530cf1Skardel "setsockopt IP_MULTICAST_IF %s fails: %m", 95945530cf1Skardel stoa(&ep->sin)); 96045530cf1Skardel break; 961b3d6264cSchristos 96245530cf1Skardel # ifdef INCLUDE_IPV6_MULTICAST_SUPPORT 96345530cf1Skardel case AF_INET6 : 96445530cf1Skardel rc = setsockopt(ep->fd, IPPROTO_IPV6, 96545530cf1Skardel IPV6_MULTICAST_IF, 96645530cf1Skardel (void *)&ep->ifindex, 96745530cf1Skardel sizeof(ep->ifindex)); 968b3d6264cSchristos /* do not complain if bound addr scope is ifindex */ 969b3d6264cSchristos if (rc && ep->ifindex != SCOPE(&ep->sin)) 97045530cf1Skardel msyslog(LOG_ERR, 97145530cf1Skardel "setsockopt IPV6_MULTICAST_IF %u for %s fails: %m", 97245530cf1Skardel ep->ifindex, stoa(&ep->sin)); 97345530cf1Skardel break; 97445530cf1Skardel # endif 97545530cf1Skardel } 97645530cf1Skardel #endif /* MCAST */ 977abb0f93cSkardel } 978abb0f93cSkardel 979abb0f93cSkardel 980abb0f93cSkardel /* 981abb0f93cSkardel * remove interface from known interface list and clean up 982abb0f93cSkardel * associated resources 983abb0f93cSkardel */ 984abb0f93cSkardel static void 985abb0f93cSkardel remove_interface( 98645530cf1Skardel endpt * ep 987abb0f93cSkardel ) 988abb0f93cSkardel { 98945530cf1Skardel endpt * unlinked; 99045530cf1Skardel endpt ** pmclisthead; 991abb0f93cSkardel sockaddr_u resmask; 992abb0f93cSkardel 99345530cf1Skardel UNLINK_SLIST(unlinked, ep_list, ep, elink, endpt); 99445530cf1Skardel if (!ep->ignore_packets && INT_MULTICAST & ep->flags) { 99545530cf1Skardel pmclisthead = (AF_INET == ep->family) 99645530cf1Skardel ? &mc4_list 99745530cf1Skardel : &mc6_list; 99845530cf1Skardel UNLINK_SLIST(unlinked, *pmclisthead, ep, mclink, endpt); 99945530cf1Skardel DPRINTF(4, ("%s %s IPv%s multicast-capable unicast local address list\n", 100045530cf1Skardel stoa(&ep->sin), 100145530cf1Skardel (unlinked != NULL) 100245530cf1Skardel ? "removed from" 100345530cf1Skardel : "not found on", 100445530cf1Skardel (AF_INET == ep->family) 100545530cf1Skardel ? "4" 100645530cf1Skardel : "6")); 100745530cf1Skardel } 100845530cf1Skardel delete_interface_from_list(ep); 1009abb0f93cSkardel 101045530cf1Skardel if (ep->fd != INVALID_SOCKET) { 1011abb0f93cSkardel msyslog(LOG_INFO, 1012abb0f93cSkardel "Deleting interface #%d %s, %s#%d, interface stats: received=%ld, sent=%ld, dropped=%ld, active_time=%ld secs", 101345530cf1Skardel ep->ifnum, 101445530cf1Skardel ep->name, 101545530cf1Skardel stoa(&ep->sin), 101645530cf1Skardel SRCPORT(&ep->sin), 101745530cf1Skardel ep->received, 101845530cf1Skardel ep->sent, 101945530cf1Skardel ep->notsent, 102045530cf1Skardel current_time - ep->starttime); 1021335f7552Schristos # ifdef HAVE_IO_COMPLETION_PORT 1022335f7552Schristos io_completion_port_remove_socket(ep->fd, ep); 1023335f7552Schristos # endif 102445530cf1Skardel close_and_delete_fd_from_list(ep->fd); 1025b3d6264cSchristos ep->fd = INVALID_SOCKET; 1026abb0f93cSkardel } 1027abb0f93cSkardel 102845530cf1Skardel if (ep->bfd != INVALID_SOCKET) { 1029abb0f93cSkardel msyslog(LOG_INFO, 1030b3d6264cSchristos "stop listening for broadcasts to %s on interface #%d %s", 1031b3d6264cSchristos stoa(&ep->bcast), ep->ifnum, ep->name); 1032335f7552Schristos # ifdef HAVE_IO_COMPLETION_PORT 1033335f7552Schristos io_completion_port_remove_socket(ep->bfd, ep); 1034335f7552Schristos # endif 103545530cf1Skardel close_and_delete_fd_from_list(ep->bfd); 1036b3d6264cSchristos ep->bfd = INVALID_SOCKET; 1037abb0f93cSkardel } 1038335f7552Schristos # ifdef HAVE_IO_COMPLETION_PORT 1039335f7552Schristos io_completion_port_remove_interface(ep); 1040335f7552Schristos # endif 1041abb0f93cSkardel 1042abb0f93cSkardel ninterfaces--; 1043b3d6264cSchristos mon_clearinterface(ep); 1044abb0f93cSkardel 1045abb0f93cSkardel /* remove restrict interface entry */ 104645530cf1Skardel SET_HOSTMASK(&resmask, AF(&ep->sin)); 104745530cf1Skardel hack_restrict(RESTRICT_REMOVEIF, &ep->sin, &resmask, 1048b3d6264cSchristos RESM_NTPONLY | RESM_INTERFACE, RES_IGNORE, 0); 1049abb0f93cSkardel } 1050abb0f93cSkardel 1051abb0f93cSkardel 1052abb0f93cSkardel static void 105345530cf1Skardel log_listen_address( 105445530cf1Skardel endpt * ep 1055abb0f93cSkardel ) 1056abb0f93cSkardel { 1057b3d6264cSchristos msyslog(LOG_INFO, "%s on %d %s %s", 105845530cf1Skardel (ep->ignore_packets) 1059abb0f93cSkardel ? "Listen and drop" 1060abb0f93cSkardel : "Listen normally", 106145530cf1Skardel ep->ifnum, 106245530cf1Skardel ep->name, 1063b3d6264cSchristos sptoa(&ep->sin)); 1064abb0f93cSkardel } 1065abb0f93cSkardel 1066abb0f93cSkardel 1067abb0f93cSkardel static void 1068abb0f93cSkardel create_wildcards( 1069abb0f93cSkardel u_short port 1070abb0f93cSkardel ) 1071abb0f93cSkardel { 107243476b9eSkardel int v4wild; 107343476b9eSkardel #ifdef INCLUDE_IPV6_SUPPORT 107443476b9eSkardel int v6wild; 107543476b9eSkardel #endif 1076abb0f93cSkardel sockaddr_u wildaddr; 1077abb0f93cSkardel nic_rule_action action; 1078abb0f93cSkardel struct interface * wildif; 1079abb0f93cSkardel 1080abb0f93cSkardel /* 1081abb0f93cSkardel * silence "potentially uninitialized" warnings from VC9 1082abb0f93cSkardel * failing to follow the logic. Ideally action could remain 1083abb0f93cSkardel * uninitialized, and the memset be the first statement under 1084abb0f93cSkardel * the first if (v4wild). 1085abb0f93cSkardel */ 1086abb0f93cSkardel action = ACTION_LISTEN; 1087b3d6264cSchristos ZERO(wildaddr); 1088abb0f93cSkardel 1089abb0f93cSkardel #ifdef INCLUDE_IPV6_SUPPORT 1090abb0f93cSkardel /* 1091abb0f93cSkardel * create pseudo-interface with wildcard IPv6 address 1092abb0f93cSkardel */ 1093abb0f93cSkardel v6wild = ipv6_works; 1094abb0f93cSkardel if (v6wild) { 1095abb0f93cSkardel /* set wildaddr to the v6 wildcard address :: */ 1096b3d6264cSchristos ZERO(wildaddr); 1097abb0f93cSkardel AF(&wildaddr) = AF_INET6; 1098abb0f93cSkardel SET_ADDR6N(&wildaddr, in6addr_any); 1099abb0f93cSkardel SET_PORT(&wildaddr, port); 1100abb0f93cSkardel SET_SCOPE(&wildaddr, 0); 1101abb0f93cSkardel 1102abb0f93cSkardel /* check for interface/nic rules affecting the wildcard */ 110345530cf1Skardel action = interface_action(NULL, &wildaddr, 0); 1104abb0f93cSkardel v6wild = (ACTION_IGNORE != action); 1105abb0f93cSkardel } 1106abb0f93cSkardel if (v6wild) { 1107abb0f93cSkardel wildif = new_interface(NULL); 1108abb0f93cSkardel 1109b3d6264cSchristos strlcpy(wildif->name, "v6wildcard", sizeof(wildif->name)); 1110abb0f93cSkardel memcpy(&wildif->sin, &wildaddr, sizeof(wildif->sin)); 1111abb0f93cSkardel wildif->family = AF_INET6; 1112abb0f93cSkardel AF(&wildif->mask) = AF_INET6; 1113abb0f93cSkardel SET_ONESMASK(&wildif->mask); 1114abb0f93cSkardel 1115abb0f93cSkardel wildif->flags = INT_UP | INT_WILDCARD; 1116abb0f93cSkardel wildif->ignore_packets = (ACTION_DROP == action); 1117abb0f93cSkardel 1118abb0f93cSkardel wildif->fd = open_socket(&wildif->sin, 0, 1, wildif); 1119abb0f93cSkardel 1120abb0f93cSkardel if (wildif->fd != INVALID_SOCKET) { 1121abb0f93cSkardel wildipv6 = wildif; 1122abb0f93cSkardel any6_interface = wildif; 1123abb0f93cSkardel add_addr_to_list(&wildif->sin, wildif); 1124abb0f93cSkardel add_interface(wildif); 112545530cf1Skardel log_listen_address(wildif); 1126abb0f93cSkardel } else { 1127abb0f93cSkardel msyslog(LOG_ERR, 1128abb0f93cSkardel "unable to bind to wildcard address %s - another process may be running - EXITING", 1129abb0f93cSkardel stoa(&wildif->sin)); 1130abb0f93cSkardel exit(1); 1131abb0f93cSkardel } 1132abb0f93cSkardel DPRINT_INTERFACE(2, (wildif, "created ", "\n")); 1133abb0f93cSkardel } 1134abb0f93cSkardel #endif 1135b3d6264cSchristos 1136b3d6264cSchristos /* 1137b3d6264cSchristos * create pseudo-interface with wildcard IPv4 address 1138b3d6264cSchristos */ 1139b3d6264cSchristos v4wild = ipv4_works; 1140b3d6264cSchristos if (v4wild) { 1141b3d6264cSchristos /* set wildaddr to the v4 wildcard address 0.0.0.0 */ 1142b3d6264cSchristos AF(&wildaddr) = AF_INET; 1143b3d6264cSchristos SET_ADDR4N(&wildaddr, INADDR_ANY); 1144b3d6264cSchristos SET_PORT(&wildaddr, port); 1145b3d6264cSchristos 1146b3d6264cSchristos /* check for interface/nic rules affecting the wildcard */ 1147b3d6264cSchristos action = interface_action(NULL, &wildaddr, 0); 1148b3d6264cSchristos v4wild = (ACTION_IGNORE != action); 1149b3d6264cSchristos } 1150b3d6264cSchristos if (v4wild) { 1151b3d6264cSchristos wildif = new_interface(NULL); 1152b3d6264cSchristos 1153b3d6264cSchristos strlcpy(wildif->name, "v4wildcard", sizeof(wildif->name)); 1154b3d6264cSchristos memcpy(&wildif->sin, &wildaddr, sizeof(wildif->sin)); 1155b3d6264cSchristos wildif->family = AF_INET; 1156b3d6264cSchristos AF(&wildif->mask) = AF_INET; 1157b3d6264cSchristos SET_ONESMASK(&wildif->mask); 1158b3d6264cSchristos 1159b3d6264cSchristos wildif->flags = INT_BROADCAST | INT_UP | INT_WILDCARD; 1160b3d6264cSchristos wildif->ignore_packets = (ACTION_DROP == action); 1161b3d6264cSchristos #if defined(MCAST) 1162b3d6264cSchristos /* 1163b3d6264cSchristos * enable multicast reception on the broadcast socket 1164b3d6264cSchristos */ 1165b3d6264cSchristos AF(&wildif->bcast) = AF_INET; 1166b3d6264cSchristos SET_ADDR4N(&wildif->bcast, INADDR_ANY); 1167b3d6264cSchristos SET_PORT(&wildif->bcast, port); 1168b3d6264cSchristos #endif /* MCAST */ 1169b3d6264cSchristos wildif->fd = open_socket(&wildif->sin, 0, 1, wildif); 1170b3d6264cSchristos 1171b3d6264cSchristos if (wildif->fd != INVALID_SOCKET) { 1172b3d6264cSchristos wildipv4 = wildif; 1173b3d6264cSchristos any_interface = wildif; 1174b3d6264cSchristos 1175b3d6264cSchristos add_addr_to_list(&wildif->sin, wildif); 1176b3d6264cSchristos add_interface(wildif); 1177b3d6264cSchristos log_listen_address(wildif); 1178b3d6264cSchristos } else { 1179b3d6264cSchristos msyslog(LOG_ERR, 1180b3d6264cSchristos "unable to bind to wildcard address %s - another process may be running - EXITING", 1181b3d6264cSchristos stoa(&wildif->sin)); 1182b3d6264cSchristos exit(1); 1183b3d6264cSchristos } 1184b3d6264cSchristos DPRINT_INTERFACE(2, (wildif, "created ", "\n")); 1185b3d6264cSchristos } 1186abb0f93cSkardel } 1187abb0f93cSkardel 1188abb0f93cSkardel 1189abb0f93cSkardel /* 1190abb0f93cSkardel * add_nic_rule() -- insert a rule entry at the head of nic_rule_list. 1191abb0f93cSkardel */ 1192abb0f93cSkardel void 1193abb0f93cSkardel add_nic_rule( 1194abb0f93cSkardel nic_rule_match match_type, 1195abb0f93cSkardel const char * if_name, /* interface name or numeric address */ 1196abb0f93cSkardel int prefixlen, 1197abb0f93cSkardel nic_rule_action action 1198abb0f93cSkardel ) 1199abb0f93cSkardel { 1200abb0f93cSkardel nic_rule * rule; 1201abb0f93cSkardel isc_boolean_t is_ip; 1202abb0f93cSkardel 1203b3d6264cSchristos rule = emalloc_zero(sizeof(*rule)); 1204abb0f93cSkardel rule->match_type = match_type; 1205abb0f93cSkardel rule->prefixlen = prefixlen; 1206abb0f93cSkardel rule->action = action; 1207abb0f93cSkardel 1208abb0f93cSkardel if (MATCH_IFNAME == match_type) { 120909f14f80Schristos REQUIRE(NULL != if_name); 1210abb0f93cSkardel rule->if_name = estrdup(if_name); 1211abb0f93cSkardel } else if (MATCH_IFADDR == match_type) { 121209f14f80Schristos REQUIRE(NULL != if_name); 121345530cf1Skardel /* set rule->addr */ 1214b3d6264cSchristos is_ip = is_ip_address(if_name, AF_UNSPEC, &rule->addr); 121509f14f80Schristos REQUIRE(is_ip); 1216abb0f93cSkardel } else 121709f14f80Schristos REQUIRE(NULL == if_name); 1218abb0f93cSkardel 1219abb0f93cSkardel LINK_SLIST(nic_rule_list, rule, next); 1220abb0f93cSkardel } 1221abb0f93cSkardel 1222abb0f93cSkardel 1223abb0f93cSkardel #ifdef DEBUG 1224abb0f93cSkardel static const char * 1225abb0f93cSkardel action_text( 1226abb0f93cSkardel nic_rule_action action 1227abb0f93cSkardel ) 1228abb0f93cSkardel { 1229abb0f93cSkardel const char *t; 1230abb0f93cSkardel 1231abb0f93cSkardel switch (action) { 1232abb0f93cSkardel 1233abb0f93cSkardel default: 1234abb0f93cSkardel t = "ERROR"; /* quiet uninit warning */ 1235abb0f93cSkardel DPRINTF(1, ("fatal: unknown nic_rule_action %d\n", 1236abb0f93cSkardel action)); 123709f14f80Schristos ENSURE(0); 1238abb0f93cSkardel break; 1239abb0f93cSkardel 1240abb0f93cSkardel case ACTION_LISTEN: 1241abb0f93cSkardel t = "listen"; 1242abb0f93cSkardel break; 1243abb0f93cSkardel 1244abb0f93cSkardel case ACTION_IGNORE: 1245abb0f93cSkardel t = "ignore"; 1246abb0f93cSkardel break; 1247abb0f93cSkardel 1248abb0f93cSkardel case ACTION_DROP: 1249abb0f93cSkardel t = "drop"; 1250abb0f93cSkardel break; 1251abb0f93cSkardel } 1252abb0f93cSkardel 1253abb0f93cSkardel return t; 1254abb0f93cSkardel } 1255abb0f93cSkardel #endif /* DEBUG */ 1256abb0f93cSkardel 1257abb0f93cSkardel 1258abb0f93cSkardel static nic_rule_action 1259abb0f93cSkardel interface_action( 1260abb0f93cSkardel char * if_name, 126145530cf1Skardel sockaddr_u * if_addr, 126245530cf1Skardel u_int32 if_flags 1263abb0f93cSkardel ) 1264abb0f93cSkardel { 1265abb0f93cSkardel nic_rule * rule; 1266abb0f93cSkardel int isloopback; 1267abb0f93cSkardel int iswildcard; 1268abb0f93cSkardel 1269b3d6264cSchristos DPRINTF(4, ("interface_action: interface %s ", 1270b3d6264cSchristos (if_name != NULL) ? if_name : "wildcard")); 1271abb0f93cSkardel 127245530cf1Skardel iswildcard = is_wildcard_addr(if_addr); 1273b3d6264cSchristos isloopback = !!(INT_LOOPBACK & if_flags); 1274abb0f93cSkardel 1275abb0f93cSkardel /* 1276abb0f93cSkardel * Find any matching NIC rule from --interface / -I or ntp.conf 1277abb0f93cSkardel * interface/nic rules. 1278abb0f93cSkardel */ 1279abb0f93cSkardel for (rule = nic_rule_list; rule != NULL; rule = rule->next) { 1280abb0f93cSkardel 1281abb0f93cSkardel switch (rule->match_type) { 1282abb0f93cSkardel 1283abb0f93cSkardel case MATCH_ALL: 1284abb0f93cSkardel /* loopback and wildcard excluded from "all" */ 1285abb0f93cSkardel if (isloopback || iswildcard) 1286abb0f93cSkardel break; 1287abb0f93cSkardel DPRINTF(4, ("nic all %s\n", 1288abb0f93cSkardel action_text(rule->action))); 1289abb0f93cSkardel return rule->action; 1290abb0f93cSkardel 1291abb0f93cSkardel case MATCH_IPV4: 129245530cf1Skardel if (IS_IPV4(if_addr)) { 1293abb0f93cSkardel DPRINTF(4, ("nic ipv4 %s\n", 1294abb0f93cSkardel action_text(rule->action))); 1295abb0f93cSkardel return rule->action; 1296abb0f93cSkardel } 1297abb0f93cSkardel break; 1298abb0f93cSkardel 1299abb0f93cSkardel case MATCH_IPV6: 130045530cf1Skardel if (IS_IPV6(if_addr)) { 1301abb0f93cSkardel DPRINTF(4, ("nic ipv6 %s\n", 1302abb0f93cSkardel action_text(rule->action))); 1303abb0f93cSkardel return rule->action; 1304abb0f93cSkardel } 1305abb0f93cSkardel break; 1306abb0f93cSkardel 1307abb0f93cSkardel case MATCH_WILDCARD: 1308abb0f93cSkardel if (iswildcard) { 1309abb0f93cSkardel DPRINTF(4, ("nic wildcard %s\n", 1310abb0f93cSkardel action_text(rule->action))); 1311abb0f93cSkardel return rule->action; 1312abb0f93cSkardel } 1313abb0f93cSkardel break; 1314abb0f93cSkardel 1315abb0f93cSkardel case MATCH_IFADDR: 1316abb0f93cSkardel if (rule->prefixlen != -1) { 131745530cf1Skardel if (addr_eqprefix(if_addr, &rule->addr, 131845530cf1Skardel rule->prefixlen)) { 1319abb0f93cSkardel 1320abb0f93cSkardel DPRINTF(4, ("subnet address match - %s\n", 1321abb0f93cSkardel action_text(rule->action))); 1322abb0f93cSkardel return rule->action; 1323abb0f93cSkardel } 1324abb0f93cSkardel } else 132545530cf1Skardel if (SOCK_EQ(if_addr, &rule->addr)) { 1326abb0f93cSkardel 1327abb0f93cSkardel DPRINTF(4, ("address match - %s\n", 1328abb0f93cSkardel action_text(rule->action))); 1329abb0f93cSkardel return rule->action; 1330abb0f93cSkardel } 1331abb0f93cSkardel break; 1332abb0f93cSkardel 1333abb0f93cSkardel case MATCH_IFNAME: 1334abb0f93cSkardel if (if_name != NULL 1335ad131110Schristos #if defined(HAVE_FNMATCH) && defined(FNM_CASEFOLD) 1336ad131110Schristos && !fnmatch(rule->if_name, if_name, FNM_CASEFOLD) 1337ad131110Schristos #else 1338ad131110Schristos && !strcasecmp(if_name, rule->if_name) 1339ad131110Schristos #endif 1340ad131110Schristos ) { 1341abb0f93cSkardel 1342abb0f93cSkardel DPRINTF(4, ("interface name match - %s\n", 1343abb0f93cSkardel action_text(rule->action))); 1344abb0f93cSkardel return rule->action; 1345abb0f93cSkardel } 1346abb0f93cSkardel break; 1347abb0f93cSkardel } 1348abb0f93cSkardel } 1349abb0f93cSkardel 1350abb0f93cSkardel /* 1351abb0f93cSkardel * Unless explicitly disabled such as with "nic ignore ::1" 1352abb0f93cSkardel * listen on loopback addresses. Since ntpq and ntpdc query 1353abb0f93cSkardel * "localhost" by default, which typically resolves to ::1 and 1354abb0f93cSkardel * 127.0.0.1, it's useful to default to listening on both. 1355abb0f93cSkardel */ 1356abb0f93cSkardel if (isloopback) { 1357abb0f93cSkardel DPRINTF(4, ("default loopback listen\n")); 1358abb0f93cSkardel return ACTION_LISTEN; 1359abb0f93cSkardel } 1360abb0f93cSkardel 1361abb0f93cSkardel /* 1362abb0f93cSkardel * Treat wildcard addresses specially. If there is no explicit 1363abb0f93cSkardel * "nic ... wildcard" or "nic ... 0.0.0.0" or "nic ... ::" rule 1364abb0f93cSkardel * default to drop. 1365abb0f93cSkardel */ 1366abb0f93cSkardel if (iswildcard) { 1367abb0f93cSkardel DPRINTF(4, ("default wildcard drop\n")); 1368abb0f93cSkardel return ACTION_DROP; 1369abb0f93cSkardel } 1370abb0f93cSkardel 1371abb0f93cSkardel /* 1372abb0f93cSkardel * Check for "virtual IP" (colon in the interface name) after 1373abb0f93cSkardel * the rules so that "ntpd --interface eth0:1 -novirtualips" 1374abb0f93cSkardel * does indeed listen on eth0:1's addresses. 1375abb0f93cSkardel */ 1376abb0f93cSkardel if (!listen_to_virtual_ips && if_name != NULL 1377abb0f93cSkardel && (strchr(if_name, ':') != NULL)) { 1378abb0f93cSkardel 1379abb0f93cSkardel DPRINTF(4, ("virtual ip - ignore\n")); 1380abb0f93cSkardel return ACTION_IGNORE; 1381abb0f93cSkardel } 1382abb0f93cSkardel 1383abb0f93cSkardel /* 1384abb0f93cSkardel * If there are no --interface/-I command-line options and no 1385abb0f93cSkardel * interface/nic rules in ntp.conf, the default action is to 1386abb0f93cSkardel * listen. In the presence of rules from either, the default 1387abb0f93cSkardel * is to ignore. This implements ntpd's traditional listen- 1388abb0f93cSkardel * every default with no interface listen configuration, and 1389abb0f93cSkardel * ensures a single -I eth0 or "nic listen eth0" means do not 1390abb0f93cSkardel * listen on any other addresses. 1391abb0f93cSkardel */ 1392abb0f93cSkardel if (NULL == nic_rule_list) { 1393abb0f93cSkardel DPRINTF(4, ("default listen\n")); 1394abb0f93cSkardel return ACTION_LISTEN; 1395abb0f93cSkardel } 1396abb0f93cSkardel 1397abb0f93cSkardel DPRINTF(4, ("implicit ignore\n")); 1398abb0f93cSkardel return ACTION_IGNORE; 1399abb0f93cSkardel } 1400abb0f93cSkardel 1401abb0f93cSkardel 1402abb0f93cSkardel static void 1403abb0f93cSkardel convert_isc_if( 1404abb0f93cSkardel isc_interface_t *isc_if, 140545530cf1Skardel endpt *itf, 1406abb0f93cSkardel u_short port 1407abb0f93cSkardel ) 1408abb0f93cSkardel { 140945530cf1Skardel const u_char v6loop[16] = {0, 0, 0, 0, 0, 0, 0, 0, 141045530cf1Skardel 0, 0, 0, 0, 0, 0, 0, 1}; 141145530cf1Skardel 1412b3d6264cSchristos strlcpy(itf->name, isc_if->name, sizeof(itf->name)); 141345530cf1Skardel itf->ifindex = isc_if->ifindex; 1414abb0f93cSkardel itf->family = (u_short)isc_if->af; 1415abb0f93cSkardel AF(&itf->sin) = itf->family; 1416abb0f93cSkardel AF(&itf->mask) = itf->family; 1417abb0f93cSkardel AF(&itf->bcast) = itf->family; 1418abb0f93cSkardel SET_PORT(&itf->sin, port); 1419abb0f93cSkardel SET_PORT(&itf->mask, port); 1420abb0f93cSkardel SET_PORT(&itf->bcast, port); 1421abb0f93cSkardel 1422abb0f93cSkardel if (IS_IPV4(&itf->sin)) { 1423abb0f93cSkardel NSRCADR(&itf->sin) = isc_if->address.type.in.s_addr; 1424abb0f93cSkardel NSRCADR(&itf->mask) = isc_if->netmask.type.in.s_addr; 1425abb0f93cSkardel 1426abb0f93cSkardel if (isc_if->flags & INTERFACE_F_BROADCAST) { 1427abb0f93cSkardel itf->flags |= INT_BROADCAST; 1428abb0f93cSkardel NSRCADR(&itf->bcast) = 1429abb0f93cSkardel isc_if->broadcast.type.in.s_addr; 1430abb0f93cSkardel } 1431abb0f93cSkardel } 1432abb0f93cSkardel #ifdef INCLUDE_IPV6_SUPPORT 1433abb0f93cSkardel else if (IS_IPV6(&itf->sin)) { 1434abb0f93cSkardel SET_ADDR6N(&itf->sin, isc_if->address.type.in6); 1435abb0f93cSkardel SET_ADDR6N(&itf->mask, isc_if->netmask.type.in6); 1436abb0f93cSkardel 143745530cf1Skardel SET_SCOPE(&itf->sin, isc_if->address.zone); 1438abb0f93cSkardel } 1439abb0f93cSkardel #endif /* INCLUDE_IPV6_SUPPORT */ 1440abb0f93cSkardel 1441abb0f93cSkardel 1442abb0f93cSkardel /* Process the rest of the flags */ 1443abb0f93cSkardel 1444abb0f93cSkardel itf->flags |= 1445abb0f93cSkardel ((INTERFACE_F_UP & isc_if->flags) 1446abb0f93cSkardel ? INT_UP : 0) 1447abb0f93cSkardel | ((INTERFACE_F_LOOPBACK & isc_if->flags) 1448abb0f93cSkardel ? INT_LOOPBACK : 0) 1449abb0f93cSkardel | ((INTERFACE_F_POINTTOPOINT & isc_if->flags) 1450abb0f93cSkardel ? INT_PPP : 0) 1451abb0f93cSkardel | ((INTERFACE_F_MULTICAST & isc_if->flags) 1452abb0f93cSkardel ? INT_MULTICAST : 0) 145345530cf1Skardel | ((INTERFACE_F_PRIVACY & isc_if->flags) 145445530cf1Skardel ? INT_PRIVACY : 0) 1455abb0f93cSkardel ; 145645530cf1Skardel 145745530cf1Skardel /* 145845530cf1Skardel * Clear the loopback flag if the address is not localhost. 145945530cf1Skardel * http://bugs.ntp.org/1683 146045530cf1Skardel */ 146145530cf1Skardel if (INT_LOOPBACK & itf->flags) { 146245530cf1Skardel if (AF_INET == itf->family) { 146345530cf1Skardel if (127 != (SRCADR(&itf->sin) >> 24)) 146445530cf1Skardel itf->flags &= ~INT_LOOPBACK; 146545530cf1Skardel } else { 146645530cf1Skardel if (memcmp(v6loop, NSRCADR6(&itf->sin), 146745530cf1Skardel sizeof(NSRCADR6(&itf->sin)))) 146845530cf1Skardel itf->flags &= ~INT_LOOPBACK; 146945530cf1Skardel } 147045530cf1Skardel } 1471abb0f93cSkardel } 1472abb0f93cSkardel 1473abb0f93cSkardel 1474abb0f93cSkardel /* 1475abb0f93cSkardel * refresh_interface 1476abb0f93cSkardel * 1477abb0f93cSkardel * some OSes have been observed to keep 1478abb0f93cSkardel * cached routes even when more specific routes 1479abb0f93cSkardel * become available. 1480abb0f93cSkardel * this can be mitigated by re-binding 1481abb0f93cSkardel * the socket. 1482abb0f93cSkardel */ 1483abb0f93cSkardel static int 1484abb0f93cSkardel refresh_interface( 1485abb0f93cSkardel struct interface * interface 1486abb0f93cSkardel ) 1487abb0f93cSkardel { 1488abb0f93cSkardel #ifdef OS_MISSES_SPECIFIC_ROUTE_UPDATES 1489abb0f93cSkardel if (interface->fd != INVALID_SOCKET) { 1490b3d6264cSchristos int bcast = (interface->flags & INT_BCASTXMIT) != 0; 1491b3d6264cSchristos /* as we forcibly close() the socket remove the 1492b3d6264cSchristos broadcast permission indication */ 1493b3d6264cSchristos if (bcast) 1494b3d6264cSchristos socket_broadcast_disable(interface, &interface->sin); 1495b3d6264cSchristos 1496abb0f93cSkardel close_and_delete_fd_from_list(interface->fd); 1497b3d6264cSchristos 1498b3d6264cSchristos /* create new socket picking up a new first hop binding 1499b3d6264cSchristos at connect() time */ 1500abb0f93cSkardel interface->fd = open_socket(&interface->sin, 1501766d83b9Skardel bcast, 0, interface); 1502abb0f93cSkardel /* 1503abb0f93cSkardel * reset TTL indication so TTL is is set again 1504abb0f93cSkardel * next time around 1505abb0f93cSkardel */ 1506abb0f93cSkardel interface->last_ttl = 0; 1507abb0f93cSkardel return (interface->fd != INVALID_SOCKET); 1508abb0f93cSkardel } else 1509abb0f93cSkardel return 0; /* invalid sockets are not refreshable */ 1510abb0f93cSkardel #else /* !OS_MISSES_SPECIFIC_ROUTE_UPDATES */ 1511abb0f93cSkardel return (interface->fd != INVALID_SOCKET); 1512abb0f93cSkardel #endif /* !OS_MISSES_SPECIFIC_ROUTE_UPDATES */ 1513abb0f93cSkardel } 1514abb0f93cSkardel 1515abb0f93cSkardel /* 1516abb0f93cSkardel * interface_update - externally callable update function 1517abb0f93cSkardel */ 1518abb0f93cSkardel void 1519abb0f93cSkardel interface_update( 1520abb0f93cSkardel interface_receiver_t receiver, 1521abb0f93cSkardel void * data) 1522abb0f93cSkardel { 1523abb0f93cSkardel int new_interface_found; 1524abb0f93cSkardel 1525abb0f93cSkardel if (disable_dynamic_updates) 1526abb0f93cSkardel return; 1527abb0f93cSkardel 1528abb0f93cSkardel BLOCKIO(); 1529abb0f93cSkardel new_interface_found = update_interfaces(NTP_PORT, receiver, data); 1530abb0f93cSkardel UNBLOCKIO(); 1531abb0f93cSkardel 1532abb0f93cSkardel if (!new_interface_found) 1533abb0f93cSkardel return; 1534abb0f93cSkardel 1535abb0f93cSkardel #ifdef DEBUG 1536abb0f93cSkardel msyslog(LOG_DEBUG, "new interface(s) found: waking up resolver"); 1537abb0f93cSkardel #endif 1538b3d6264cSchristos interrupt_worker_sleep(); 1539abb0f93cSkardel } 1540abb0f93cSkardel 1541abb0f93cSkardel 1542abb0f93cSkardel /* 1543abb0f93cSkardel * sau_from_netaddr() - convert network address on-wire formats. 1544abb0f93cSkardel * Convert from libisc's isc_netaddr_t to NTP's sockaddr_u 1545abb0f93cSkardel */ 1546abb0f93cSkardel void 1547abb0f93cSkardel sau_from_netaddr( 1548abb0f93cSkardel sockaddr_u *psau, 1549abb0f93cSkardel const isc_netaddr_t *pna 1550abb0f93cSkardel ) 1551abb0f93cSkardel { 1552b3d6264cSchristos ZERO_SOCK(psau); 1553abb0f93cSkardel AF(psau) = (u_short)pna->family; 1554abb0f93cSkardel switch (pna->family) { 1555abb0f93cSkardel 1556abb0f93cSkardel case AF_INET: 1557abb0f93cSkardel memcpy(&psau->sa4.sin_addr, &pna->type.in, 1558abb0f93cSkardel sizeof(psau->sa4.sin_addr)); 1559abb0f93cSkardel break; 1560abb0f93cSkardel 1561abb0f93cSkardel case AF_INET6: 1562abb0f93cSkardel memcpy(&psau->sa6.sin6_addr, &pna->type.in6, 1563abb0f93cSkardel sizeof(psau->sa6.sin6_addr)); 1564abb0f93cSkardel break; 1565abb0f93cSkardel } 1566abb0f93cSkardel } 1567abb0f93cSkardel 1568abb0f93cSkardel 1569abb0f93cSkardel static int 1570abb0f93cSkardel is_wildcard_addr( 157145530cf1Skardel const sockaddr_u *psau 1572abb0f93cSkardel ) 1573abb0f93cSkardel { 1574abb0f93cSkardel if (IS_IPV4(psau) && !NSRCADR(psau)) 1575abb0f93cSkardel return 1; 1576abb0f93cSkardel 1577abb0f93cSkardel #ifdef INCLUDE_IPV6_SUPPORT 1578abb0f93cSkardel if (IS_IPV6(psau) && S_ADDR6_EQ(psau, &in6addr_any)) 1579abb0f93cSkardel return 1; 1580abb0f93cSkardel #endif 1581abb0f93cSkardel 1582abb0f93cSkardel return 0; 1583abb0f93cSkardel } 1584abb0f93cSkardel 1585abb0f93cSkardel 1586abb0f93cSkardel #ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND 1587abb0f93cSkardel /* 1588abb0f93cSkardel * enable/disable re-use of wildcard address socket 1589abb0f93cSkardel */ 1590abb0f93cSkardel static void 1591abb0f93cSkardel set_wildcard_reuse( 1592abb0f93cSkardel u_short family, 1593abb0f93cSkardel int on 1594abb0f93cSkardel ) 1595abb0f93cSkardel { 1596abb0f93cSkardel struct interface *any; 1597abb0f93cSkardel SOCKET fd = INVALID_SOCKET; 1598abb0f93cSkardel 1599abb0f93cSkardel any = ANY_INTERFACE_BYFAM(family); 1600abb0f93cSkardel if (any != NULL) 1601abb0f93cSkardel fd = any->fd; 1602abb0f93cSkardel 1603abb0f93cSkardel if (fd != INVALID_SOCKET) { 1604abb0f93cSkardel if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 1605abb0f93cSkardel (char *)&on, sizeof(on))) 1606abb0f93cSkardel msyslog(LOG_ERR, 1607abb0f93cSkardel "set_wildcard_reuse: setsockopt(SO_REUSEADDR, %s) failed: %m", 1608abb0f93cSkardel on ? "on" : "off"); 1609abb0f93cSkardel 1610abb0f93cSkardel DPRINTF(4, ("set SO_REUSEADDR to %s on %s\n", 1611abb0f93cSkardel on ? "on" : "off", 1612abb0f93cSkardel stoa(&any->sin))); 1613abb0f93cSkardel } 1614abb0f93cSkardel } 1615abb0f93cSkardel #endif /* OS_NEEDS_REUSEADDR_FOR_IFADDRBIND */ 1616abb0f93cSkardel 16177469785fSroy static isc_boolean_t 16187469785fSroy check_flags( 16197469785fSroy sockaddr_u *psau, 16207469785fSroy const char *name, 16217469785fSroy u_int32 flags 16227469785fSroy ) 16237469785fSroy { 16247469785fSroy #if defined(SIOCGIFAFLAG_IN) 16257469785fSroy struct ifreq ifr; 16267469785fSroy int fd; 16277469785fSroy 16287469785fSroy if (psau->sa.sa_family != AF_INET) 16297469785fSroy return ISC_FALSE; 16307469785fSroy if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 16317469785fSroy return ISC_FALSE; 16327469785fSroy ZERO(ifr); 16337469785fSroy memcpy(&ifr.ifr_addr, &psau->sa, sizeof(ifr.ifr_addr)); 16347469785fSroy strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 16357469785fSroy if (ioctl(fd, SIOCGIFAFLAG_IN, &ifr) < 0) { 16367469785fSroy close(fd); 16377469785fSroy return ISC_FALSE; 16387469785fSroy } 16397469785fSroy close(fd); 16407469785fSroy if ((ifr.ifr_addrflags & flags) != 0) 16417469785fSroy return ISC_TRUE; 16427469785fSroy #endif /* SIOCGIFAFLAG_IN */ 16437469785fSroy return ISC_FALSE; 16447469785fSroy } 164545530cf1Skardel 164645530cf1Skardel static isc_boolean_t 1647df44c210Sroy check_flags6( 164845530cf1Skardel sockaddr_u *psau, 1649df44c210Sroy const char *name, 1650df44c210Sroy u_int32 flags6 165145530cf1Skardel ) 165245530cf1Skardel { 1653df44c210Sroy #if defined(INCLUDE_IPV6_SUPPORT) && defined(SIOCGIFAFLAG_IN6) 165445530cf1Skardel struct in6_ifreq ifr6; 165545530cf1Skardel int fd; 165645530cf1Skardel 165745530cf1Skardel if (psau->sa.sa_family != AF_INET6) 165845530cf1Skardel return ISC_FALSE; 165945530cf1Skardel if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 166045530cf1Skardel return ISC_FALSE; 1661b3d6264cSchristos ZERO(ifr6); 166245530cf1Skardel memcpy(&ifr6.ifr_addr, &psau->sa6, sizeof(ifr6.ifr_addr)); 1663b3d6264cSchristos strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 166445530cf1Skardel if (ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) < 0) { 166545530cf1Skardel close(fd); 166645530cf1Skardel return ISC_FALSE; 166745530cf1Skardel } 166845530cf1Skardel close(fd); 1669df44c210Sroy if ((ifr6.ifr_ifru.ifru_flags6 & flags6) != 0) 167045530cf1Skardel return ISC_TRUE; 1671df44c210Sroy #endif /* INCLUDE_IPV6_SUPPORT && SIOCGIFAFLAG_IN6 */ 167245530cf1Skardel return ISC_FALSE; 167345530cf1Skardel } 167445530cf1Skardel 1675df44c210Sroy static isc_boolean_t 1676df44c210Sroy is_anycast( 1677df44c210Sroy sockaddr_u *psau, 1678df44c210Sroy const char *name 1679df44c210Sroy ) 1680df44c210Sroy { 1681df44c210Sroy #ifdef IN6_IFF_ANYCAST 1682df44c210Sroy return check_flags6(psau, name, IN6_IFF_ANYCAST); 1683df44c210Sroy #else 1684df44c210Sroy return ISC_FALSE; 1685df44c210Sroy #endif 1686df44c210Sroy } 1687df44c210Sroy 1688df44c210Sroy static isc_boolean_t 1689df44c210Sroy is_valid( 1690df44c210Sroy sockaddr_u *psau, 1691df44c210Sroy const char *name 1692df44c210Sroy ) 1693df44c210Sroy { 16947469785fSroy u_int32 flags; 1695df44c210Sroy 16967469785fSroy flags = 0; 16977469785fSroy switch (psau->sa.sa_family) { 16987469785fSroy case AF_INET: 16997469785fSroy #ifdef IN_IFF_DETACHED 17007469785fSroy flags |= IN_IFF_DETACHED; 17017469785fSroy #endif 17027469785fSroy #ifdef IN_IFF_TENTATIVE 17037469785fSroy flags |= IN_IFF_TENTATIVE; 17047469785fSroy #endif 17057469785fSroy return check_flags(psau, name, flags) ? ISC_FALSE : ISC_TRUE; 17067469785fSroy case AF_INET6: 1707df44c210Sroy #ifdef IN6_IFF_DEPARTED 17087469785fSroy flags |= IN6_IFF_DEPARTED; 1709df44c210Sroy #endif 1710df44c210Sroy #ifdef IN6_IFF_DETACHED 17117469785fSroy flags |= IN6_IFF_DETACHED; 1712df44c210Sroy #endif 1713df44c210Sroy #ifdef IN6_IFF_TENTATIVE 17147469785fSroy flags |= IN6_IFF_TENTATIVE; 1715df44c210Sroy #endif 17167469785fSroy return check_flags6(psau, name, flags) ? ISC_FALSE : ISC_TRUE; 17177469785fSroy default: 17187469785fSroy return ISC_FALSE; 17197469785fSroy } 1720df44c210Sroy } 172145530cf1Skardel 1722abb0f93cSkardel /* 1723abb0f93cSkardel * update_interface strategy 1724abb0f93cSkardel * 1725abb0f93cSkardel * toggle configuration phase 1726abb0f93cSkardel * 1727abb0f93cSkardel * Phase 1: 1728abb0f93cSkardel * forall currently existing interfaces 1729abb0f93cSkardel * if address is known: 1730abb0f93cSkardel * drop socket - rebind again 1731abb0f93cSkardel * 1732abb0f93cSkardel * if address is NOT known: 1733abb0f93cSkardel * attempt to create a new interface entry 1734abb0f93cSkardel * 1735abb0f93cSkardel * Phase 2: 1736abb0f93cSkardel * forall currently known non MCAST and WILDCARD interfaces 1737abb0f93cSkardel * if interface does not match configuration phase (not seen in phase 1): 1738abb0f93cSkardel * remove interface from known interface list 1739abb0f93cSkardel * forall peers associated with this interface 1740abb0f93cSkardel * disconnect peer from this interface 1741abb0f93cSkardel * 1742abb0f93cSkardel * Phase 3: 1743abb0f93cSkardel * attempt to re-assign interfaces to peers 1744abb0f93cSkardel * 1745abb0f93cSkardel */ 1746abb0f93cSkardel 1747abb0f93cSkardel static int 1748abb0f93cSkardel update_interfaces( 1749abb0f93cSkardel u_short port, 1750abb0f93cSkardel interface_receiver_t receiver, 1751abb0f93cSkardel void * data 1752abb0f93cSkardel ) 1753abb0f93cSkardel { 1754abb0f93cSkardel isc_mem_t * mctx = (void *)-1; 1755abb0f93cSkardel interface_info_t ifi; 1756abb0f93cSkardel isc_interfaceiter_t * iter; 1757abb0f93cSkardel isc_result_t result; 1758abb0f93cSkardel isc_interface_t isc_if; 1759abb0f93cSkardel int new_interface_found; 1760abb0f93cSkardel unsigned int family; 176145530cf1Skardel endpt enumep; 176245530cf1Skardel endpt * ep; 176345530cf1Skardel endpt * next_ep; 1764abb0f93cSkardel 1765abb0f93cSkardel DPRINTF(3, ("update_interfaces(%d)\n", port)); 1766abb0f93cSkardel 1767abb0f93cSkardel /* 1768abb0f93cSkardel * phase one - scan interfaces 1769abb0f93cSkardel * - create those that are not found 1770abb0f93cSkardel * - update those that are found 1771abb0f93cSkardel */ 1772abb0f93cSkardel 177345530cf1Skardel new_interface_found = FALSE; 1774abb0f93cSkardel iter = NULL; 1775abb0f93cSkardel result = isc_interfaceiter_create(mctx, &iter); 1776abb0f93cSkardel 1777abb0f93cSkardel if (result != ISC_R_SUCCESS) 1778abb0f93cSkardel return 0; 1779abb0f93cSkardel 1780abb0f93cSkardel /* 1781abb0f93cSkardel * Toggle system interface scan phase to find untouched 1782abb0f93cSkardel * interfaces to be deleted. 1783abb0f93cSkardel */ 1784abb0f93cSkardel sys_interphase ^= 0x1; 1785abb0f93cSkardel 1786abb0f93cSkardel for (result = isc_interfaceiter_first(iter); 1787abb0f93cSkardel ISC_R_SUCCESS == result; 1788abb0f93cSkardel result = isc_interfaceiter_next(iter)) { 1789abb0f93cSkardel 1790abb0f93cSkardel result = isc_interfaceiter_current(iter, &isc_if); 1791abb0f93cSkardel 1792abb0f93cSkardel if (result != ISC_R_SUCCESS) 1793abb0f93cSkardel break; 1794abb0f93cSkardel 1795abb0f93cSkardel /* See if we have a valid family to use */ 1796abb0f93cSkardel family = isc_if.address.family; 1797abb0f93cSkardel if (AF_INET != family && AF_INET6 != family) 1798abb0f93cSkardel continue; 1799abb0f93cSkardel if (AF_INET == family && !ipv4_works) 1800abb0f93cSkardel continue; 1801abb0f93cSkardel if (AF_INET6 == family && !ipv6_works) 1802abb0f93cSkardel continue; 1803abb0f93cSkardel 1804abb0f93cSkardel /* create prototype */ 180545530cf1Skardel init_interface(&enumep); 1806abb0f93cSkardel 180745530cf1Skardel convert_isc_if(&isc_if, &enumep, port); 1808abb0f93cSkardel 1809b3d6264cSchristos DPRINT_INTERFACE(4, (&enumep, "examining ", "\n")); 1810b3d6264cSchristos 1811abb0f93cSkardel /* 1812abb0f93cSkardel * Check if and how we are going to use the interface. 1813abb0f93cSkardel */ 181445530cf1Skardel switch (interface_action(enumep.name, &enumep.sin, 181545530cf1Skardel enumep.flags)) { 1816abb0f93cSkardel 1817abb0f93cSkardel case ACTION_IGNORE: 1818b3d6264cSchristos DPRINTF(4, ("ignoring interface %s (%s) - by nic rules\n", 1819b3d6264cSchristos enumep.name, stoa(&enumep.sin))); 1820abb0f93cSkardel continue; 1821abb0f93cSkardel 1822abb0f93cSkardel case ACTION_LISTEN: 1823b3d6264cSchristos DPRINTF(4, ("listen interface %s (%s) - by nic rules\n", 1824b3d6264cSchristos enumep.name, stoa(&enumep.sin))); 182545530cf1Skardel enumep.ignore_packets = ISC_FALSE; 1826abb0f93cSkardel break; 1827abb0f93cSkardel 1828abb0f93cSkardel case ACTION_DROP: 1829b3d6264cSchristos DPRINTF(4, ("drop on interface %s (%s) - by nic rules\n", 1830b3d6264cSchristos enumep.name, stoa(&enumep.sin))); 183145530cf1Skardel enumep.ignore_packets = ISC_TRUE; 1832abb0f93cSkardel break; 1833abb0f93cSkardel } 1834abb0f93cSkardel 1835abb0f93cSkardel /* interfaces must be UP to be usable */ 183645530cf1Skardel if (!(enumep.flags & INT_UP)) { 1837abb0f93cSkardel DPRINTF(4, ("skipping interface %s (%s) - DOWN\n", 183845530cf1Skardel enumep.name, stoa(&enumep.sin))); 1839abb0f93cSkardel continue; 1840abb0f93cSkardel } 1841abb0f93cSkardel 1842abb0f93cSkardel /* 1843abb0f93cSkardel * skip any interfaces UP and bound to a wildcard 1844abb0f93cSkardel * address - some dhcp clients produce that in the 1845abb0f93cSkardel * wild 1846abb0f93cSkardel */ 184745530cf1Skardel if (is_wildcard_addr(&enumep.sin)) 184845530cf1Skardel continue; 184945530cf1Skardel 185045530cf1Skardel if (is_anycast(&enumep.sin, isc_if.name)) 1851abb0f93cSkardel continue; 1852abb0f93cSkardel 1853abb0f93cSkardel /* 1854df44c210Sroy * skip any address that is an invalid state to be used 1855df44c210Sroy */ 1856df44c210Sroy if (!is_valid(&enumep.sin, isc_if.name)) 1857df44c210Sroy continue; 1858df44c210Sroy 1859df44c210Sroy /* 1860abb0f93cSkardel * map to local *address* in order to map all duplicate 186145530cf1Skardel * interfaces to an endpt structure with the appropriate 186245530cf1Skardel * socket. Our name space is (ip-address), NOT 186345530cf1Skardel * (interface name, ip-address). 1864abb0f93cSkardel */ 186545530cf1Skardel ep = getinterface(&enumep.sin, INT_WILDCARD); 1866abb0f93cSkardel 186745530cf1Skardel if (ep != NULL && refresh_interface(ep)) { 1868abb0f93cSkardel /* 1869abb0f93cSkardel * found existing and up to date interface - 1870abb0f93cSkardel * mark present. 1871abb0f93cSkardel */ 187245530cf1Skardel if (ep->phase != sys_interphase) { 1873abb0f93cSkardel /* 1874abb0f93cSkardel * On a new round we reset the name so 1875abb0f93cSkardel * the interface name shows up again if 1876abb0f93cSkardel * this address is no longer shared. 187745530cf1Skardel * We reset ignore_packets from the 187845530cf1Skardel * new prototype to respect any runtime 187945530cf1Skardel * changes to the nic rules. 1880abb0f93cSkardel */ 1881b3d6264cSchristos strlcpy(ep->name, enumep.name, 188245530cf1Skardel sizeof(ep->name)); 188345530cf1Skardel ep->ignore_packets = 188445530cf1Skardel enumep.ignore_packets; 188545530cf1Skardel } else { 1886abb0f93cSkardel /* name collision - rename interface */ 1887b3d6264cSchristos strlcpy(ep->name, "*multiple*", 188845530cf1Skardel sizeof(ep->name)); 188945530cf1Skardel } 1890abb0f93cSkardel 189145530cf1Skardel DPRINT_INTERFACE(4, (ep, "updating ", 1892abb0f93cSkardel " present\n")); 1893abb0f93cSkardel 189445530cf1Skardel if (ep->ignore_packets != 189545530cf1Skardel enumep.ignore_packets) { 1896abb0f93cSkardel /* 1897abb0f93cSkardel * We have conflicting configurations 1898abb0f93cSkardel * for the interface address. This is 1899abb0f93cSkardel * caused by using -I <interfacename> 1900abb0f93cSkardel * for an interface that shares its 1901abb0f93cSkardel * address with other interfaces. We 1902abb0f93cSkardel * can not disambiguate incoming 1903abb0f93cSkardel * packets delivered to this socket 1904abb0f93cSkardel * without extra syscalls/features. 1905abb0f93cSkardel * These are not (commonly) available. 1906abb0f93cSkardel * Note this is a more unusual 1907abb0f93cSkardel * configuration where several 1908abb0f93cSkardel * interfaces share an address but 1909abb0f93cSkardel * filtering via interface name is 1910abb0f93cSkardel * attempted. We resolve the 1911abb0f93cSkardel * configuration conflict by disabling 1912abb0f93cSkardel * the processing of received packets. 1913abb0f93cSkardel * This leads to no service on the 1914abb0f93cSkardel * interface address where the conflict 1915abb0f93cSkardel * occurs. 1916abb0f93cSkardel */ 1917abb0f93cSkardel msyslog(LOG_ERR, 1918abb0f93cSkardel "WARNING: conflicting enable configuration for interfaces %s and %s for address %s - unsupported configuration - address DISABLED", 191945530cf1Skardel enumep.name, ep->name, 192045530cf1Skardel stoa(&enumep.sin)); 1921abb0f93cSkardel 192245530cf1Skardel ep->ignore_packets = ISC_TRUE; 1923abb0f93cSkardel } 1924abb0f93cSkardel 192545530cf1Skardel ep->phase = sys_interphase; 1926abb0f93cSkardel 1927abb0f93cSkardel ifi.action = IFS_EXISTS; 192845530cf1Skardel ifi.ep = ep; 1929abb0f93cSkardel if (receiver != NULL) 1930abb0f93cSkardel (*receiver)(data, &ifi); 1931abb0f93cSkardel } else { 1932abb0f93cSkardel /* 1933abb0f93cSkardel * This is new or refreshing failed - add to 1934abb0f93cSkardel * our interface list. If refreshing failed we 1935abb0f93cSkardel * will delete the interface structure in phase 1936abb0f93cSkardel * 2 as the interface was not marked current. 1937abb0f93cSkardel * We can bind to the address as the refresh 1938abb0f93cSkardel * code already closed the offending socket 1939abb0f93cSkardel */ 194045530cf1Skardel ep = create_interface(port, &enumep); 1941abb0f93cSkardel 194245530cf1Skardel if (ep != NULL) { 1943abb0f93cSkardel ifi.action = IFS_CREATED; 194445530cf1Skardel ifi.ep = ep; 1945abb0f93cSkardel if (receiver != NULL) 1946abb0f93cSkardel (*receiver)(data, &ifi); 1947abb0f93cSkardel 194845530cf1Skardel new_interface_found = TRUE; 1949abb0f93cSkardel DPRINT_INTERFACE(3, 195045530cf1Skardel (ep, "updating ", 1951abb0f93cSkardel " new - created\n")); 1952abb0f93cSkardel } else { 1953abb0f93cSkardel DPRINT_INTERFACE(3, 195445530cf1Skardel (&enumep, "updating ", 1955abb0f93cSkardel " new - creation FAILED")); 1956abb0f93cSkardel 1957abb0f93cSkardel msyslog(LOG_INFO, 1958abb0f93cSkardel "failed to init interface for address %s", 195945530cf1Skardel stoa(&enumep.sin)); 1960abb0f93cSkardel continue; 1961abb0f93cSkardel } 1962abb0f93cSkardel } 1963abb0f93cSkardel } 1964abb0f93cSkardel 1965abb0f93cSkardel isc_interfaceiter_destroy(&iter); 1966abb0f93cSkardel 1967abb0f93cSkardel /* 1968abb0f93cSkardel * phase 2 - delete gone interfaces - reassigning peers to 1969abb0f93cSkardel * other interfaces 1970abb0f93cSkardel */ 197145530cf1Skardel for (ep = ep_list; ep != NULL; ep = next_ep) { 197245530cf1Skardel next_ep = ep->elink; 1973abb0f93cSkardel 1974abb0f93cSkardel /* 197545530cf1Skardel * if phase does not match sys_phase this interface was 197645530cf1Skardel * not enumerated during the last interface scan - so it 197745530cf1Skardel * is gone and will be deleted here unless it did not 197845530cf1Skardel * originate from interface enumeration (INT_WILDCARD, 197945530cf1Skardel * INT_MCASTIF). 1980abb0f93cSkardel */ 198145530cf1Skardel if (((INT_WILDCARD | INT_MCASTIF) & ep->flags) || 198245530cf1Skardel ep->phase == sys_interphase) 198345530cf1Skardel continue; 198445530cf1Skardel 198545530cf1Skardel DPRINT_INTERFACE(3, (ep, "updating ", 1986abb0f93cSkardel "GONE - deleting\n")); 198745530cf1Skardel remove_interface(ep); 1988abb0f93cSkardel 1989abb0f93cSkardel ifi.action = IFS_DELETED; 199045530cf1Skardel ifi.ep = ep; 1991abb0f93cSkardel if (receiver != NULL) 1992abb0f93cSkardel (*receiver)(data, &ifi); 1993abb0f93cSkardel 199445530cf1Skardel /* disconnect peers from deleted endpt. */ 199545530cf1Skardel while (ep->peers != NULL) 199645530cf1Skardel set_peerdstadr(ep->peers, NULL); 1997abb0f93cSkardel 1998abb0f93cSkardel /* 1999abb0f93cSkardel * update globals in case we lose 2000abb0f93cSkardel * a loopback interface 2001abb0f93cSkardel */ 200245530cf1Skardel if (ep == loopback_interface) 2003abb0f93cSkardel loopback_interface = NULL; 2004abb0f93cSkardel 200545530cf1Skardel delete_interface(ep); 2006abb0f93cSkardel } 2007abb0f93cSkardel 2008abb0f93cSkardel /* 2009b3d6264cSchristos * phase 3 - re-configure as the world has possibly changed 2010b3d6264cSchristos * 2011b3d6264cSchristos * never ever make this conditional again - it is needed to track 2012b3d6264cSchristos * routing updates. see bug #2506 2013abb0f93cSkardel */ 2014abb0f93cSkardel refresh_all_peerinterfaces(); 2015b3d6264cSchristos 2016b3d6264cSchristos if (broadcast_client_enabled) 2017b3d6264cSchristos io_setbclient(); 201845530cf1Skardel 2019766d83b9Skardel if (sys_bclient) 2020766d83b9Skardel io_setbclient(); 2021766d83b9Skardel 202209f14f80Schristos #ifdef MCAST 20234e3b3909Schristos /* 20244e3b3909Schristos * Check multicast interfaces and try to join multicast groups if 20254e3b3909Schristos * not joined yet. 20264e3b3909Schristos */ 20274e3b3909Schristos for (ep = ep_list; ep != NULL; ep = ep->elink) { 20284e3b3909Schristos remaddr_t *entry; 20294e3b3909Schristos 20304e3b3909Schristos if (!(INT_MCASTIF & ep->flags) || (INT_MCASTOPEN & ep->flags)) 20314e3b3909Schristos continue; 20324e3b3909Schristos 20334e3b3909Schristos /* Find remote address that was linked to this interface */ 20344e3b3909Schristos for (entry = remoteaddr_list; 20354e3b3909Schristos entry != NULL; 20364e3b3909Schristos entry = entry->link) { 20374e3b3909Schristos if (entry->ep == ep) { 20384e3b3909Schristos if (socket_multicast_enable(ep, &entry->addr)) { 20394e3b3909Schristos msyslog(LOG_INFO, 20404e3b3909Schristos "Joined %s socket to multicast group %s", 20414e3b3909Schristos stoa(&ep->sin), 20424e3b3909Schristos stoa(&entry->addr)); 20434e3b3909Schristos } 20444e3b3909Schristos break; 20454e3b3909Schristos } 20464e3b3909Schristos } 20474e3b3909Schristos } 204809f14f80Schristos #endif /* MCAST */ 20494e3b3909Schristos 2050abb0f93cSkardel return new_interface_found; 2051abb0f93cSkardel } 2052abb0f93cSkardel 2053abb0f93cSkardel 2054abb0f93cSkardel /* 2055abb0f93cSkardel * create_sockets - create a socket for each interface plus a default 2056abb0f93cSkardel * socket for when we don't know where to send 2057abb0f93cSkardel */ 2058abb0f93cSkardel static int 2059abb0f93cSkardel create_sockets( 2060abb0f93cSkardel u_short port 2061abb0f93cSkardel ) 2062abb0f93cSkardel { 2063abb0f93cSkardel #ifndef HAVE_IO_COMPLETION_PORT 2064abb0f93cSkardel /* 2065abb0f93cSkardel * I/O Completion Ports don't care about the select and FD_SET 2066abb0f93cSkardel */ 2067abb0f93cSkardel maxactivefd = 0; 2068abb0f93cSkardel FD_ZERO(&activefds); 2069abb0f93cSkardel #endif 2070abb0f93cSkardel 2071abb0f93cSkardel DPRINTF(2, ("create_sockets(%d)\n", port)); 2072abb0f93cSkardel 2073abb0f93cSkardel create_wildcards(port); 2074abb0f93cSkardel 2075abb0f93cSkardel update_interfaces(port, NULL, NULL); 2076abb0f93cSkardel 2077abb0f93cSkardel /* 2078abb0f93cSkardel * Now that we have opened all the sockets, turn off the reuse 2079abb0f93cSkardel * flag for security. 2080abb0f93cSkardel */ 2081abb0f93cSkardel set_reuseaddr(0); 2082abb0f93cSkardel 2083abb0f93cSkardel DPRINTF(2, ("create_sockets: Total interfaces = %d\n", ninterfaces)); 2084abb0f93cSkardel 2085abb0f93cSkardel return ninterfaces; 2086abb0f93cSkardel } 2087abb0f93cSkardel 2088abb0f93cSkardel /* 2089abb0f93cSkardel * create_interface - create a new interface for a given prototype 2090abb0f93cSkardel * binding the socket. 2091abb0f93cSkardel */ 2092abb0f93cSkardel static struct interface * 2093abb0f93cSkardel create_interface( 2094abb0f93cSkardel u_short port, 2095abb0f93cSkardel struct interface * protot 2096abb0f93cSkardel ) 2097abb0f93cSkardel { 2098abb0f93cSkardel sockaddr_u resmask; 209945530cf1Skardel endpt * iface; 210045530cf1Skardel #if defined(MCAST) && defined(MULTICAST_NONEWSOCKET) 210145530cf1Skardel remaddr_t * entry; 210245530cf1Skardel remaddr_t * next_entry; 210345530cf1Skardel #endif 2104abb0f93cSkardel DPRINTF(2, ("create_interface(%s#%d)\n", stoa(&protot->sin), 2105abb0f93cSkardel port)); 2106abb0f93cSkardel 2107abb0f93cSkardel /* build an interface */ 2108abb0f93cSkardel iface = new_interface(protot); 2109abb0f93cSkardel 2110abb0f93cSkardel /* 2111abb0f93cSkardel * create socket 2112abb0f93cSkardel */ 2113abb0f93cSkardel iface->fd = open_socket(&iface->sin, 0, 0, iface); 2114abb0f93cSkardel 2115abb0f93cSkardel if (iface->fd != INVALID_SOCKET) 211645530cf1Skardel log_listen_address(iface); 2117abb0f93cSkardel 2118abb0f93cSkardel if ((INT_BROADCAST & iface->flags) 2119abb0f93cSkardel && iface->bfd != INVALID_SOCKET) 2120abb0f93cSkardel msyslog(LOG_INFO, "Listening on broadcast address %s#%d", 2121abb0f93cSkardel stoa((&iface->bcast)), port); 2122abb0f93cSkardel 2123abb0f93cSkardel if (INVALID_SOCKET == iface->fd 2124abb0f93cSkardel && INVALID_SOCKET == iface->bfd) { 2125abb0f93cSkardel msyslog(LOG_ERR, "unable to create socket on %s (%d) for %s#%d", 2126abb0f93cSkardel iface->name, 2127abb0f93cSkardel iface->ifnum, 2128abb0f93cSkardel stoa((&iface->sin)), 2129abb0f93cSkardel port); 2130abb0f93cSkardel delete_interface(iface); 2131abb0f93cSkardel return NULL; 2132abb0f93cSkardel } 2133abb0f93cSkardel 2134abb0f93cSkardel /* 2135abb0f93cSkardel * Blacklist our own addresses, no use talking to ourself 2136abb0f93cSkardel */ 2137abb0f93cSkardel SET_HOSTMASK(&resmask, AF(&iface->sin)); 2138abb0f93cSkardel hack_restrict(RESTRICT_FLAGS, &iface->sin, &resmask, 2139b3d6264cSchristos RESM_NTPONLY | RESM_INTERFACE, RES_IGNORE, 0); 2140abb0f93cSkardel 2141abb0f93cSkardel /* 2142abb0f93cSkardel * set globals with the first found 2143abb0f93cSkardel * loopback interface of the appropriate class 2144abb0f93cSkardel */ 2145abb0f93cSkardel if (NULL == loopback_interface && AF_INET == iface->family 2146abb0f93cSkardel && (INT_LOOPBACK & iface->flags)) 2147abb0f93cSkardel loopback_interface = iface; 2148abb0f93cSkardel 2149abb0f93cSkardel /* 2150abb0f93cSkardel * put into our interface list 2151abb0f93cSkardel */ 2152abb0f93cSkardel add_addr_to_list(&iface->sin, iface); 2153abb0f93cSkardel add_interface(iface); 2154abb0f93cSkardel 215545530cf1Skardel #if defined(MCAST) && defined(MULTICAST_NONEWSOCKET) 215645530cf1Skardel /* 215745530cf1Skardel * Join any previously-configured compatible multicast groups. 215845530cf1Skardel */ 215945530cf1Skardel if (INT_MULTICAST & iface->flags && 216045530cf1Skardel !((INT_LOOPBACK | INT_WILDCARD) & iface->flags) && 216145530cf1Skardel !iface->ignore_packets) { 216245530cf1Skardel for (entry = remoteaddr_list; 216345530cf1Skardel entry != NULL; 216445530cf1Skardel entry = next_entry) { 216545530cf1Skardel next_entry = entry->link; 216645530cf1Skardel if (AF(&iface->sin) != AF(&entry->addr) || 216745530cf1Skardel !IS_MCAST(&entry->addr)) 216845530cf1Skardel continue; 216945530cf1Skardel if (socket_multicast_enable(iface, 217045530cf1Skardel &entry->addr)) 217145530cf1Skardel msyslog(LOG_INFO, 217245530cf1Skardel "Joined %s socket to multicast group %s", 217345530cf1Skardel stoa(&iface->sin), 217445530cf1Skardel stoa(&entry->addr)); 217545530cf1Skardel else 217645530cf1Skardel msyslog(LOG_ERR, 217745530cf1Skardel "Failed to join %s socket to multicast group %s", 217845530cf1Skardel stoa(&iface->sin), 217945530cf1Skardel stoa(&entry->addr)); 218045530cf1Skardel } 218145530cf1Skardel } 218245530cf1Skardel #endif /* MCAST && MCAST_NONEWSOCKET */ 218345530cf1Skardel 2184abb0f93cSkardel DPRINT_INTERFACE(2, (iface, "created ", "\n")); 2185abb0f93cSkardel return iface; 2186abb0f93cSkardel } 2187abb0f93cSkardel 2188abb0f93cSkardel 2189abb0f93cSkardel #ifdef SO_EXCLUSIVEADDRUSE 2190abb0f93cSkardel static void 2191abb0f93cSkardel set_excladdruse( 2192abb0f93cSkardel SOCKET fd 2193abb0f93cSkardel ) 2194abb0f93cSkardel { 2195abb0f93cSkardel int one = 1; 2196abb0f93cSkardel int failed; 2197abb0f93cSkardel #ifdef SYS_WINNT 2198abb0f93cSkardel DWORD err; 2199abb0f93cSkardel #endif 2200abb0f93cSkardel 2201abb0f93cSkardel failed = setsockopt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 2202abb0f93cSkardel (char *)&one, sizeof(one)); 2203abb0f93cSkardel 2204abb0f93cSkardel if (!failed) 2205abb0f93cSkardel return; 2206abb0f93cSkardel 2207abb0f93cSkardel #ifdef SYS_WINNT 2208abb0f93cSkardel /* 2209abb0f93cSkardel * Prior to Windows XP setting SO_EXCLUSIVEADDRUSE can fail with 2210abb0f93cSkardel * error WSAINVAL depending on service pack level and whether 2211abb0f93cSkardel * the user account is in the Administrators group. Do not 2212abb0f93cSkardel * complain if it fails that way on versions prior to XP (5.1). 2213abb0f93cSkardel */ 2214abb0f93cSkardel err = GetLastError(); 2215abb0f93cSkardel 2216abb0f93cSkardel if (isc_win32os_versioncheck(5, 1, 0, 0) < 0 /* < 5.1/XP */ 2217abb0f93cSkardel && WSAEINVAL == err) 2218abb0f93cSkardel return; 2219abb0f93cSkardel 2220abb0f93cSkardel SetLastError(err); 2221abb0f93cSkardel #endif 2222abb0f93cSkardel msyslog(LOG_ERR, 2223abb0f93cSkardel "setsockopt(%d, SO_EXCLUSIVEADDRUSE, on): %m", 2224abb0f93cSkardel (int)fd); 2225abb0f93cSkardel } 2226abb0f93cSkardel #endif /* SO_EXCLUSIVEADDRUSE */ 2227abb0f93cSkardel 2228abb0f93cSkardel 2229abb0f93cSkardel /* 2230abb0f93cSkardel * set_reuseaddr() - set/clear REUSEADDR on all sockets 2231abb0f93cSkardel * NB possible hole - should we be doing this on broadcast 2232abb0f93cSkardel * fd's also? 2233abb0f93cSkardel */ 2234abb0f93cSkardel static void 2235abb0f93cSkardel set_reuseaddr( 2236abb0f93cSkardel int flag 2237abb0f93cSkardel ) 2238abb0f93cSkardel { 2239abb0f93cSkardel #ifndef SO_EXCLUSIVEADDRUSE 224045530cf1Skardel endpt *ep; 2241abb0f93cSkardel 224245530cf1Skardel for (ep = ep_list; ep != NULL; ep = ep->elink) { 224345530cf1Skardel if (ep->flags & INT_WILDCARD) 2244abb0f93cSkardel continue; 2245abb0f93cSkardel 2246abb0f93cSkardel /* 224745530cf1Skardel * if ep->fd is INVALID_SOCKET, we might have a adapter 2248abb0f93cSkardel * configured but not present 2249abb0f93cSkardel */ 2250abb0f93cSkardel DPRINTF(4, ("setting SO_REUSEADDR on %.16s@%s to %s\n", 225145530cf1Skardel ep->name, stoa(&ep->sin), 2252abb0f93cSkardel flag ? "on" : "off")); 2253abb0f93cSkardel 225445530cf1Skardel if (ep->fd != INVALID_SOCKET) { 225545530cf1Skardel if (setsockopt(ep->fd, SOL_SOCKET, SO_REUSEADDR, 225645530cf1Skardel (char *)&flag, sizeof(flag))) { 225745530cf1Skardel msyslog(LOG_ERR, "set_reuseaddr: setsockopt(%s, SO_REUSEADDR, %s) failed: %m", 225845530cf1Skardel stoa(&ep->sin), flag ? "on" : "off"); 2259abb0f93cSkardel } 2260abb0f93cSkardel } 2261abb0f93cSkardel } 2262abb0f93cSkardel #endif /* ! SO_EXCLUSIVEADDRUSE */ 2263abb0f93cSkardel } 2264abb0f93cSkardel 2265abb0f93cSkardel /* 2266abb0f93cSkardel * This is just a wrapper around an internal function so we can 2267abb0f93cSkardel * make other changes as necessary later on 2268abb0f93cSkardel */ 2269abb0f93cSkardel void 2270abb0f93cSkardel enable_broadcast( 2271abb0f93cSkardel struct interface * iface, 2272abb0f93cSkardel sockaddr_u * baddr 2273abb0f93cSkardel ) 2274abb0f93cSkardel { 2275abb0f93cSkardel #ifdef OPEN_BCAST_SOCKET 2276abb0f93cSkardel socket_broadcast_enable(iface, iface->fd, baddr); 2277abb0f93cSkardel #endif 2278abb0f93cSkardel } 2279abb0f93cSkardel 2280abb0f93cSkardel #ifdef OPEN_BCAST_SOCKET 2281abb0f93cSkardel /* 2282abb0f93cSkardel * Enable a broadcast address to a given socket 2283b3d6264cSchristos * The socket is in the ep_list all we need to do is enable 2284abb0f93cSkardel * broadcasting. It is not this function's job to select the socket 2285abb0f93cSkardel */ 2286abb0f93cSkardel static isc_boolean_t 2287abb0f93cSkardel socket_broadcast_enable( 2288abb0f93cSkardel struct interface * iface, 2289abb0f93cSkardel SOCKET fd, 2290abb0f93cSkardel sockaddr_u * baddr 2291abb0f93cSkardel ) 2292abb0f93cSkardel { 2293abb0f93cSkardel #ifdef SO_BROADCAST 2294abb0f93cSkardel int on = 1; 2295abb0f93cSkardel 2296abb0f93cSkardel if (IS_IPV4(baddr)) { 2297abb0f93cSkardel /* if this interface can support broadcast, set SO_BROADCAST */ 2298abb0f93cSkardel if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, 2299abb0f93cSkardel (char *)&on, sizeof(on))) 2300abb0f93cSkardel msyslog(LOG_ERR, 2301abb0f93cSkardel "setsockopt(SO_BROADCAST) enable failure on address %s: %m", 2302abb0f93cSkardel stoa(baddr)); 2303abb0f93cSkardel else 2304abb0f93cSkardel DPRINTF(2, ("Broadcast enabled on socket %d for address %s\n", 2305abb0f93cSkardel fd, stoa(baddr))); 2306abb0f93cSkardel } 2307b3d6264cSchristos iface->flags |= INT_BCASTXMIT; 2308abb0f93cSkardel return ISC_TRUE; 2309abb0f93cSkardel #else 2310abb0f93cSkardel return ISC_FALSE; 2311abb0f93cSkardel #endif /* SO_BROADCAST */ 2312abb0f93cSkardel } 2313abb0f93cSkardel 2314ad131110Schristos #ifdef OS_MISSES_SPECIFIC_ROUTE_UPDATES 2315abb0f93cSkardel /* 2316abb0f93cSkardel * Remove a broadcast address from a given socket 2317b3d6264cSchristos * The socket is in the ep_list all we need to do is disable 2318abb0f93cSkardel * broadcasting. It is not this function's job to select the socket 2319abb0f93cSkardel */ 2320abb0f93cSkardel static isc_boolean_t 2321abb0f93cSkardel socket_broadcast_disable( 2322abb0f93cSkardel struct interface * iface, 2323abb0f93cSkardel sockaddr_u * baddr 2324abb0f93cSkardel ) 2325abb0f93cSkardel { 2326abb0f93cSkardel #ifdef SO_BROADCAST 2327abb0f93cSkardel int off = 0; /* This seems to be OK as an int */ 2328abb0f93cSkardel 2329abb0f93cSkardel if (IS_IPV4(baddr) && setsockopt(iface->fd, SOL_SOCKET, 2330abb0f93cSkardel SO_BROADCAST, (char *)&off, sizeof(off))) 2331abb0f93cSkardel msyslog(LOG_ERR, 2332abb0f93cSkardel "setsockopt(SO_BROADCAST) disable failure on address %s: %m", 2333abb0f93cSkardel stoa(baddr)); 2334abb0f93cSkardel 2335b3d6264cSchristos iface->flags &= ~INT_BCASTXMIT; 2336abb0f93cSkardel return ISC_TRUE; 2337abb0f93cSkardel #else 2338abb0f93cSkardel return ISC_FALSE; 2339abb0f93cSkardel #endif /* SO_BROADCAST */ 2340abb0f93cSkardel } 2341ad131110Schristos #endif /* OS_MISSES_SPECIFIC_ROUTE_UPDATES */ 2342abb0f93cSkardel 2343abb0f93cSkardel #endif /* OPEN_BCAST_SOCKET */ 2344abb0f93cSkardel 2345abb0f93cSkardel /* 2346abb0f93cSkardel * return the broadcast client flag value 2347abb0f93cSkardel */ 2348abb0f93cSkardel isc_boolean_t 2349abb0f93cSkardel get_broadcastclient_flag(void) 2350abb0f93cSkardel { 2351abb0f93cSkardel return (broadcast_client_enabled); 2352abb0f93cSkardel } 2353335f7552Schristos 2354abb0f93cSkardel /* 2355abb0f93cSkardel * Check to see if the address is a multicast address 2356abb0f93cSkardel */ 2357abb0f93cSkardel static isc_boolean_t 2358abb0f93cSkardel addr_ismulticast( 2359abb0f93cSkardel sockaddr_u *maddr 2360abb0f93cSkardel ) 2361abb0f93cSkardel { 2362abb0f93cSkardel isc_boolean_t result; 2363abb0f93cSkardel 2364abb0f93cSkardel #ifndef INCLUDE_IPV6_MULTICAST_SUPPORT 2365abb0f93cSkardel /* 2366abb0f93cSkardel * If we don't have IPV6 support any IPV6 addr is not multicast 2367abb0f93cSkardel */ 2368abb0f93cSkardel if (IS_IPV6(maddr)) 2369abb0f93cSkardel result = ISC_FALSE; 2370abb0f93cSkardel else 2371abb0f93cSkardel #endif 2372abb0f93cSkardel result = IS_MCAST(maddr); 2373abb0f93cSkardel 2374abb0f93cSkardel if (!result) 2375abb0f93cSkardel DPRINTF(4, ("address %s is not multicast\n", 2376abb0f93cSkardel stoa(maddr))); 2377abb0f93cSkardel 2378abb0f93cSkardel return result; 2379abb0f93cSkardel } 2380abb0f93cSkardel 2381abb0f93cSkardel /* 2382abb0f93cSkardel * Multicast servers need to set the appropriate Multicast interface 2383abb0f93cSkardel * socket option in order for it to know which interface to use for 2384abb0f93cSkardel * send the multicast packet. 2385abb0f93cSkardel */ 2386abb0f93cSkardel void 2387abb0f93cSkardel enable_multicast_if( 2388abb0f93cSkardel struct interface * iface, 2389abb0f93cSkardel sockaddr_u * maddr 2390abb0f93cSkardel ) 2391abb0f93cSkardel { 2392abb0f93cSkardel #ifdef MCAST 2393b3d6264cSchristos #ifdef IP_MULTICAST_LOOP 2394abb0f93cSkardel TYPEOF_IP_MULTICAST_LOOP off = 0; 2395b3d6264cSchristos #endif 239670953dd2Sprlw1 #if defined(INCLUDE_IPV6_MULTICAST_SUPPORT) && defined(IPV6_MULTICAST_LOOP) 2397b3d6264cSchristos u_int off6 = 0; 2398b3d6264cSchristos #endif 2399abb0f93cSkardel 240009f14f80Schristos REQUIRE(AF(maddr) == AF(&iface->sin)); 2401abb0f93cSkardel 2402abb0f93cSkardel switch (AF(&iface->sin)) { 2403abb0f93cSkardel 2404abb0f93cSkardel case AF_INET: 2405abb0f93cSkardel #ifdef IP_MULTICAST_LOOP 2406abb0f93cSkardel /* 2407abb0f93cSkardel * Don't send back to itself, but allow failure to set 2408abb0f93cSkardel */ 2409abb0f93cSkardel if (setsockopt(iface->fd, IPPROTO_IP, 2410abb0f93cSkardel IP_MULTICAST_LOOP, 2411abb0f93cSkardel SETSOCKOPT_ARG_CAST &off, 2412abb0f93cSkardel sizeof(off))) { 2413abb0f93cSkardel 2414abb0f93cSkardel msyslog(LOG_ERR, 2415abb0f93cSkardel "setsockopt IP_MULTICAST_LOOP failed: %m on socket %d, addr %s for multicast address %s", 2416abb0f93cSkardel iface->fd, stoa(&iface->sin), 2417abb0f93cSkardel stoa(maddr)); 2418abb0f93cSkardel } 2419abb0f93cSkardel #endif 2420abb0f93cSkardel break; 2421abb0f93cSkardel 2422abb0f93cSkardel case AF_INET6: 2423abb0f93cSkardel #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT 2424abb0f93cSkardel #ifdef IPV6_MULTICAST_LOOP 2425abb0f93cSkardel /* 2426abb0f93cSkardel * Don't send back to itself, but allow failure to set 2427abb0f93cSkardel */ 2428abb0f93cSkardel if (setsockopt(iface->fd, IPPROTO_IPV6, 2429abb0f93cSkardel IPV6_MULTICAST_LOOP, 2430b3d6264cSchristos (char *) &off6, sizeof(off6))) { 2431abb0f93cSkardel 2432abb0f93cSkardel msyslog(LOG_ERR, 2433b3d6264cSchristos "setsockopt IPV6_MULTICAST_LOOP failed: %m on socket %d, addr %s for multicast address %s", 2434abb0f93cSkardel iface->fd, stoa(&iface->sin), 2435abb0f93cSkardel stoa(maddr)); 2436abb0f93cSkardel } 2437abb0f93cSkardel #endif 2438abb0f93cSkardel break; 2439abb0f93cSkardel #else 2440abb0f93cSkardel return; 2441abb0f93cSkardel #endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ 2442abb0f93cSkardel } 2443abb0f93cSkardel return; 2444abb0f93cSkardel #endif 2445abb0f93cSkardel } 2446abb0f93cSkardel 2447abb0f93cSkardel /* 2448abb0f93cSkardel * Add a multicast address to a given socket 2449b3d6264cSchristos * The socket is in the ep_list all we need to do is enable 2450abb0f93cSkardel * multicasting. It is not this function's job to select the socket 2451abb0f93cSkardel */ 245245530cf1Skardel #if defined(MCAST) 2453abb0f93cSkardel static isc_boolean_t 2454abb0f93cSkardel socket_multicast_enable( 245545530cf1Skardel endpt * iface, 2456abb0f93cSkardel sockaddr_u * maddr 2457abb0f93cSkardel ) 2458abb0f93cSkardel { 2459abb0f93cSkardel struct ip_mreq mreq; 2460abb0f93cSkardel # ifdef INCLUDE_IPV6_MULTICAST_SUPPORT 2461abb0f93cSkardel struct ipv6_mreq mreq6; 2462abb0f93cSkardel # endif 2463abb0f93cSkardel switch (AF(maddr)) { 2464abb0f93cSkardel 2465abb0f93cSkardel case AF_INET: 2466b3d6264cSchristos ZERO(mreq); 2467abb0f93cSkardel mreq.imr_multiaddr = SOCK_ADDR4(maddr); 2468abb0f93cSkardel mreq.imr_interface.s_addr = htonl(INADDR_ANY); 2469abb0f93cSkardel if (setsockopt(iface->fd, 2470abb0f93cSkardel IPPROTO_IP, 2471abb0f93cSkardel IP_ADD_MEMBERSHIP, 2472abb0f93cSkardel (char *)&mreq, 2473abb0f93cSkardel sizeof(mreq))) { 24744e3b3909Schristos DPRINTF(2, ( 2475abb0f93cSkardel "setsockopt IP_ADD_MEMBERSHIP failed: %m on socket %d, addr %s for %x / %x (%s)", 2476abb0f93cSkardel iface->fd, stoa(&iface->sin), 2477abb0f93cSkardel mreq.imr_multiaddr.s_addr, 2478abb0f93cSkardel mreq.imr_interface.s_addr, 24794e3b3909Schristos stoa(maddr))); 2480abb0f93cSkardel return ISC_FALSE; 2481abb0f93cSkardel } 2482abb0f93cSkardel DPRINTF(4, ("Added IPv4 multicast membership on socket %d, addr %s for %x / %x (%s)\n", 2483abb0f93cSkardel iface->fd, stoa(&iface->sin), 2484abb0f93cSkardel mreq.imr_multiaddr.s_addr, 2485abb0f93cSkardel mreq.imr_interface.s_addr, stoa(maddr))); 2486abb0f93cSkardel break; 2487abb0f93cSkardel 2488abb0f93cSkardel case AF_INET6: 2489abb0f93cSkardel # ifdef INCLUDE_IPV6_MULTICAST_SUPPORT 2490abb0f93cSkardel /* 2491abb0f93cSkardel * Enable reception of multicast packets. 2492abb0f93cSkardel * If the address is link-local we can get the 2493abb0f93cSkardel * interface index from the scope id. Don't do this 2494abb0f93cSkardel * for other types of multicast addresses. For now let 2495abb0f93cSkardel * the kernel figure it out. 2496abb0f93cSkardel */ 2497b3d6264cSchristos ZERO(mreq6); 2498abb0f93cSkardel mreq6.ipv6mr_multiaddr = SOCK_ADDR6(maddr); 249945530cf1Skardel mreq6.ipv6mr_interface = iface->ifindex; 2500abb0f93cSkardel 2501abb0f93cSkardel if (setsockopt(iface->fd, IPPROTO_IPV6, 2502abb0f93cSkardel IPV6_JOIN_GROUP, (char *)&mreq6, 2503abb0f93cSkardel sizeof(mreq6))) { 25044e3b3909Schristos DPRINTF(2, ( 250545530cf1Skardel "setsockopt IPV6_JOIN_GROUP failed: %m on socket %d, addr %s for interface %u (%s)", 2506abb0f93cSkardel iface->fd, stoa(&iface->sin), 25074e3b3909Schristos mreq6.ipv6mr_interface, stoa(maddr))); 2508abb0f93cSkardel return ISC_FALSE; 2509abb0f93cSkardel } 251045530cf1Skardel DPRINTF(4, ("Added IPv6 multicast group on socket %d, addr %s for interface %u (%s)\n", 2511abb0f93cSkardel iface->fd, stoa(&iface->sin), 2512abb0f93cSkardel mreq6.ipv6mr_interface, stoa(maddr))); 2513abb0f93cSkardel # else 2514abb0f93cSkardel return ISC_FALSE; 2515abb0f93cSkardel # endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ 2516abb0f93cSkardel } 2517abb0f93cSkardel iface->flags |= INT_MCASTOPEN; 2518abb0f93cSkardel iface->num_mcast++; 251945530cf1Skardel 2520abb0f93cSkardel return ISC_TRUE; 2521abb0f93cSkardel } 252245530cf1Skardel #endif /* MCAST */ 252345530cf1Skardel 2524abb0f93cSkardel 2525abb0f93cSkardel /* 2526abb0f93cSkardel * Remove a multicast address from a given socket 2527b3d6264cSchristos * The socket is in the ep_list all we need to do is disable 2528abb0f93cSkardel * multicasting. It is not this function's job to select the socket 2529abb0f93cSkardel */ 253045530cf1Skardel #ifdef MCAST 2531abb0f93cSkardel static isc_boolean_t 2532abb0f93cSkardel socket_multicast_disable( 2533abb0f93cSkardel struct interface * iface, 2534abb0f93cSkardel sockaddr_u * maddr 2535abb0f93cSkardel ) 2536abb0f93cSkardel { 2537abb0f93cSkardel # ifdef INCLUDE_IPV6_MULTICAST_SUPPORT 2538abb0f93cSkardel struct ipv6_mreq mreq6; 2539abb0f93cSkardel # endif 2540abb0f93cSkardel struct ip_mreq mreq; 2541abb0f93cSkardel 2542b3d6264cSchristos ZERO(mreq); 2543abb0f93cSkardel 2544abb0f93cSkardel if (find_addr_in_list(maddr) == NULL) { 2545abb0f93cSkardel DPRINTF(4, ("socket_multicast_disable(%s): not found\n", 2546abb0f93cSkardel stoa(maddr))); 2547abb0f93cSkardel return ISC_TRUE; 2548abb0f93cSkardel } 2549abb0f93cSkardel 2550abb0f93cSkardel switch (AF(maddr)) { 2551abb0f93cSkardel 2552abb0f93cSkardel case AF_INET: 2553abb0f93cSkardel mreq.imr_multiaddr = SOCK_ADDR4(maddr); 2554abb0f93cSkardel mreq.imr_interface = SOCK_ADDR4(&iface->sin); 2555abb0f93cSkardel if (setsockopt(iface->fd, IPPROTO_IP, 2556abb0f93cSkardel IP_DROP_MEMBERSHIP, (char *)&mreq, 2557abb0f93cSkardel sizeof(mreq))) { 2558abb0f93cSkardel 2559abb0f93cSkardel msyslog(LOG_ERR, 2560abb0f93cSkardel "setsockopt IP_DROP_MEMBERSHIP failed: %m on socket %d, addr %s for %x / %x (%s)", 2561abb0f93cSkardel iface->fd, stoa(&iface->sin), 2562abb0f93cSkardel SRCADR(maddr), SRCADR(&iface->sin), 2563abb0f93cSkardel stoa(maddr)); 2564abb0f93cSkardel return ISC_FALSE; 2565abb0f93cSkardel } 2566abb0f93cSkardel break; 2567abb0f93cSkardel case AF_INET6: 2568abb0f93cSkardel # ifdef INCLUDE_IPV6_MULTICAST_SUPPORT 2569abb0f93cSkardel /* 2570abb0f93cSkardel * Disable reception of multicast packets 2571abb0f93cSkardel * If the address is link-local we can get the 2572abb0f93cSkardel * interface index from the scope id. Don't do this 2573abb0f93cSkardel * for other types of multicast addresses. For now let 2574abb0f93cSkardel * the kernel figure it out. 2575abb0f93cSkardel */ 2576abb0f93cSkardel mreq6.ipv6mr_multiaddr = SOCK_ADDR6(maddr); 257745530cf1Skardel mreq6.ipv6mr_interface = iface->ifindex; 2578abb0f93cSkardel 2579abb0f93cSkardel if (setsockopt(iface->fd, IPPROTO_IPV6, 2580abb0f93cSkardel IPV6_LEAVE_GROUP, (char *)&mreq6, 2581abb0f93cSkardel sizeof(mreq6))) { 2582abb0f93cSkardel 2583abb0f93cSkardel msyslog(LOG_ERR, 2584abb0f93cSkardel "setsockopt IPV6_LEAVE_GROUP failure: %m on socket %d, addr %s for %d (%s)", 2585abb0f93cSkardel iface->fd, stoa(&iface->sin), 258645530cf1Skardel iface->ifindex, stoa(maddr)); 2587abb0f93cSkardel return ISC_FALSE; 2588abb0f93cSkardel } 2589abb0f93cSkardel break; 2590abb0f93cSkardel # else 2591abb0f93cSkardel return ISC_FALSE; 2592abb0f93cSkardel # endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ 2593abb0f93cSkardel } 2594abb0f93cSkardel 2595abb0f93cSkardel iface->num_mcast--; 2596abb0f93cSkardel if (!iface->num_mcast) 2597abb0f93cSkardel iface->flags &= ~INT_MCASTOPEN; 2598abb0f93cSkardel 2599abb0f93cSkardel return ISC_TRUE; 2600abb0f93cSkardel } 2601abb0f93cSkardel #endif /* MCAST */ 2602abb0f93cSkardel 2603abb0f93cSkardel /* 2604abb0f93cSkardel * io_setbclient - open the broadcast client sockets 2605abb0f93cSkardel */ 2606abb0f93cSkardel void 2607abb0f93cSkardel io_setbclient(void) 2608abb0f93cSkardel { 2609abb0f93cSkardel #ifdef OPEN_BCAST_SOCKET 2610abb0f93cSkardel struct interface * interf; 2611*1c24ec91Schristos unsigned int nif; 2612abb0f93cSkardel 2613abb0f93cSkardel nif = 0; 2614abb0f93cSkardel set_reuseaddr(1); 2615abb0f93cSkardel 261645530cf1Skardel for (interf = ep_list; 2617abb0f93cSkardel interf != NULL; 261845530cf1Skardel interf = interf->elink) { 2619abb0f93cSkardel 2620abb0f93cSkardel if (interf->flags & (INT_WILDCARD | INT_LOOPBACK)) 2621abb0f93cSkardel continue; 2622abb0f93cSkardel 2623abb0f93cSkardel /* use only allowed addresses */ 2624abb0f93cSkardel if (interf->ignore_packets) 2625abb0f93cSkardel continue; 2626abb0f93cSkardel 2627abb0f93cSkardel /* Need a broadcast-capable interface */ 2628abb0f93cSkardel if (!(interf->flags & INT_BROADCAST)) 2629abb0f93cSkardel continue; 2630abb0f93cSkardel 2631abb0f93cSkardel /* Only IPv4 addresses are valid for broadcast */ 2632335f7552Schristos REQUIRE(IS_IPV4(&interf->bcast)); 2633abb0f93cSkardel 2634abb0f93cSkardel /* Do we already have the broadcast address open? */ 2635abb0f93cSkardel if (interf->flags & INT_BCASTOPEN) { 2636abb0f93cSkardel /* 2637abb0f93cSkardel * account for already open interfaces to avoid 2638abb0f93cSkardel * misleading warning below 2639abb0f93cSkardel */ 2640abb0f93cSkardel nif++; 2641abb0f93cSkardel continue; 2642abb0f93cSkardel } 2643abb0f93cSkardel 2644abb0f93cSkardel /* 2645abb0f93cSkardel * Try to open the broadcast address 2646abb0f93cSkardel */ 2647abb0f93cSkardel interf->family = AF_INET; 2648abb0f93cSkardel interf->bfd = open_socket(&interf->bcast, 1, 0, interf); 2649abb0f93cSkardel 2650abb0f93cSkardel /* 2651abb0f93cSkardel * If we succeeded then we use it otherwise enable 2652abb0f93cSkardel * broadcast on the interface address 2653abb0f93cSkardel */ 2654abb0f93cSkardel if (interf->bfd != INVALID_SOCKET) { 2655abb0f93cSkardel nif++; 2656b3d6264cSchristos interf->flags |= INT_BCASTOPEN; 2657abb0f93cSkardel msyslog(LOG_INFO, 2658b3d6264cSchristos "Listen for broadcasts to %s on interface #%d %s", 2659b3d6264cSchristos stoa(&interf->bcast), interf->ifnum, interf->name); 2660335f7552Schristos } else switch (errno) { 2661335f7552Schristos /* Silently ignore EADDRINUSE as we probably 2662335f7552Schristos * opened the socket already for an address in 2663335f7552Schristos * the same network */ 2664335f7552Schristos case EADDRINUSE: 2665335f7552Schristos /* Some systems cannot bind a socket to a broadcast 2666335f7552Schristos * address, as that is not a valid host address. */ 2667335f7552Schristos case EADDRNOTAVAIL: 2668335f7552Schristos # ifdef SYS_WINNT /*TODO: use for other systems, too? */ 2669335f7552Schristos /* avoid recurrence here -- if we already have a 2670335f7552Schristos * regular socket, it's quite useless to try this 2671335f7552Schristos * again. 2672335f7552Schristos */ 2673335f7552Schristos if (interf->fd != INVALID_SOCKET) { 2674335f7552Schristos interf->flags |= INT_BCASTOPEN; 2675335f7552Schristos nif++; 2676335f7552Schristos } 2677335f7552Schristos # endif 2678335f7552Schristos break; 2679335f7552Schristos 2680335f7552Schristos default: 2681b3d6264cSchristos msyslog(LOG_INFO, 2682b3d6264cSchristos "failed to listen for broadcasts to %s on interface #%d %s", 2683b3d6264cSchristos stoa(&interf->bcast), interf->ifnum, interf->name); 2684335f7552Schristos break; 2685abb0f93cSkardel } 2686abb0f93cSkardel } 2687abb0f93cSkardel set_reuseaddr(0); 2688*1c24ec91Schristos if (nif != 0) { 2689b3d6264cSchristos broadcast_client_enabled = ISC_TRUE; 2690b3d6264cSchristos DPRINTF(1, ("io_setbclient: listening to %d broadcast addresses\n", nif)); 2691*1c24ec91Schristos } else { 2692b3d6264cSchristos broadcast_client_enabled = ISC_FALSE; 2693abb0f93cSkardel msyslog(LOG_ERR, 2694abb0f93cSkardel "Unable to listen for broadcasts, no broadcast interfaces available"); 2695b3d6264cSchristos } 2696abb0f93cSkardel #else 2697abb0f93cSkardel msyslog(LOG_ERR, 2698abb0f93cSkardel "io_setbclient: Broadcast Client disabled by build"); 2699abb0f93cSkardel #endif /* OPEN_BCAST_SOCKET */ 2700abb0f93cSkardel } 2701abb0f93cSkardel 2702abb0f93cSkardel /* 2703abb0f93cSkardel * io_unsetbclient - close the broadcast client sockets 2704abb0f93cSkardel */ 2705abb0f93cSkardel void 2706abb0f93cSkardel io_unsetbclient(void) 2707abb0f93cSkardel { 270845530cf1Skardel endpt *ep; 2709abb0f93cSkardel 271045530cf1Skardel for (ep = ep_list; ep != NULL; ep = ep->elink) { 271145530cf1Skardel if (INT_WILDCARD & ep->flags) 2712abb0f93cSkardel continue; 271345530cf1Skardel if (!(INT_BCASTOPEN & ep->flags)) 2714abb0f93cSkardel continue; 2715b3d6264cSchristos 2716b3d6264cSchristos if (ep->bfd != INVALID_SOCKET) { 2717b3d6264cSchristos /* destroy broadcast listening socket */ 2718b3d6264cSchristos msyslog(LOG_INFO, 2719b3d6264cSchristos "stop listening for broadcasts to %s on interface #%d %s", 2720b3d6264cSchristos stoa(&ep->bcast), ep->ifnum, ep->name); 2721335f7552Schristos # ifdef HAVE_IO_COMPLETION_PORT 2722335f7552Schristos io_completion_port_remove_socket(ep->bfd, ep); 2723335f7552Schristos # endif 2724b3d6264cSchristos close_and_delete_fd_from_list(ep->bfd); 2725b3d6264cSchristos ep->bfd = INVALID_SOCKET; 2726abb0f93cSkardel } 2727335f7552Schristos ep->flags &= ~INT_BCASTOPEN; 2728abb0f93cSkardel } 2729b3d6264cSchristos broadcast_client_enabled = ISC_FALSE; 2730b3d6264cSchristos } 2731abb0f93cSkardel 2732abb0f93cSkardel /* 2733abb0f93cSkardel * io_multicast_add() - add multicast group address 2734abb0f93cSkardel */ 2735abb0f93cSkardel void 2736abb0f93cSkardel io_multicast_add( 2737abb0f93cSkardel sockaddr_u *addr 2738abb0f93cSkardel ) 2739abb0f93cSkardel { 2740abb0f93cSkardel #ifdef MCAST 274145530cf1Skardel endpt * ep; 274245530cf1Skardel endpt * one_ep; 2743abb0f93cSkardel 2744abb0f93cSkardel /* 2745abb0f93cSkardel * Check to see if this is a multicast address 2746abb0f93cSkardel */ 2747abb0f93cSkardel if (!addr_ismulticast(addr)) 2748abb0f93cSkardel return; 2749abb0f93cSkardel 2750abb0f93cSkardel /* If we already have it we can just return */ 2751abb0f93cSkardel if (NULL != find_flagged_addr_in_list(addr, INT_MCASTOPEN)) { 2752abb0f93cSkardel msyslog(LOG_INFO, 2753abb0f93cSkardel "Duplicate request found for multicast address %s", 2754abb0f93cSkardel stoa(addr)); 2755abb0f93cSkardel return; 2756abb0f93cSkardel } 2757abb0f93cSkardel 2758abb0f93cSkardel # ifndef MULTICAST_NONEWSOCKET 275945530cf1Skardel ep = new_interface(NULL); 2760abb0f93cSkardel 2761abb0f93cSkardel /* 2762abb0f93cSkardel * Open a new socket for the multicast address 2763abb0f93cSkardel */ 276445530cf1Skardel ep->sin = *addr; 276545530cf1Skardel SET_PORT(&ep->sin, NTP_PORT); 276645530cf1Skardel ep->family = AF(&ep->sin); 276745530cf1Skardel AF(&ep->mask) = ep->family; 276845530cf1Skardel SET_ONESMASK(&ep->mask); 2769abb0f93cSkardel 2770abb0f93cSkardel set_reuseaddr(1); 277145530cf1Skardel ep->bfd = INVALID_SOCKET; 277245530cf1Skardel ep->fd = open_socket(&ep->sin, 0, 0, ep); 277345530cf1Skardel if (ep->fd != INVALID_SOCKET) { 277445530cf1Skardel ep->ignore_packets = ISC_FALSE; 277545530cf1Skardel ep->flags |= INT_MCASTIF; 2776abb0f93cSkardel 2777b3d6264cSchristos strlcpy(ep->name, "multicast", sizeof(ep->name)); 277845530cf1Skardel DPRINT_INTERFACE(2, (ep, "multicast add ", "\n")); 277945530cf1Skardel add_interface(ep); 278045530cf1Skardel log_listen_address(ep); 2781abb0f93cSkardel } else { 2782abb0f93cSkardel /* bind failed, re-use wildcard interface */ 278345530cf1Skardel delete_interface(ep); 2784abb0f93cSkardel 2785abb0f93cSkardel if (IS_IPV4(addr)) 278645530cf1Skardel ep = wildipv4; 2787abb0f93cSkardel else if (IS_IPV6(addr)) 278845530cf1Skardel ep = wildipv6; 2789abb0f93cSkardel else 279045530cf1Skardel ep = NULL; 2791abb0f93cSkardel 279245530cf1Skardel if (ep != NULL) { 2793abb0f93cSkardel /* HACK ! -- stuff in an address */ 2794abb0f93cSkardel /* because we don't bind addr? DH */ 279545530cf1Skardel ep->bcast = *addr; 2796abb0f93cSkardel msyslog(LOG_ERR, 2797abb0f93cSkardel "multicast address %s using wildcard interface #%d %s", 279845530cf1Skardel stoa(addr), ep->ifnum, ep->name); 2799abb0f93cSkardel } else { 2800abb0f93cSkardel msyslog(LOG_ERR, 2801abb0f93cSkardel "No multicast socket available to use for address %s", 2802abb0f93cSkardel stoa(addr)); 2803abb0f93cSkardel return; 2804abb0f93cSkardel } 2805abb0f93cSkardel } 280645530cf1Skardel { /* in place of the { following for in #else clause */ 280745530cf1Skardel one_ep = ep; 280845530cf1Skardel # else /* MULTICAST_NONEWSOCKET follows */ 2809abb0f93cSkardel /* 281045530cf1Skardel * For the case where we can't use a separate socket (Windows) 281145530cf1Skardel * join each applicable endpoint socket to the group address. 2812abb0f93cSkardel */ 281345530cf1Skardel if (IS_IPV4(addr)) 281445530cf1Skardel one_ep = wildipv4; 281545530cf1Skardel else 281645530cf1Skardel one_ep = wildipv6; 281745530cf1Skardel for (ep = ep_list; ep != NULL; ep = ep->elink) { 281845530cf1Skardel if (ep->ignore_packets || AF(&ep->sin) != AF(addr) || 281945530cf1Skardel !(INT_MULTICAST & ep->flags) || 282045530cf1Skardel (INT_LOOPBACK | INT_WILDCARD) & ep->flags) 282145530cf1Skardel continue; 282245530cf1Skardel one_ep = ep; 282345530cf1Skardel # endif /* MULTICAST_NONEWSOCKET */ 282445530cf1Skardel if (socket_multicast_enable(ep, addr)) 282545530cf1Skardel msyslog(LOG_INFO, 282645530cf1Skardel "Joined %s socket to multicast group %s", 282745530cf1Skardel stoa(&ep->sin), 2828abb0f93cSkardel stoa(addr)); 2829abb0f93cSkardel } 2830abb0f93cSkardel 283145530cf1Skardel add_addr_to_list(addr, one_ep); 283245530cf1Skardel #else /* !MCAST follows*/ 2833abb0f93cSkardel msyslog(LOG_ERR, 2834abb0f93cSkardel "Can not add multicast address %s: no multicast support", 2835abb0f93cSkardel stoa(addr)); 283645530cf1Skardel #endif 2837abb0f93cSkardel return; 2838abb0f93cSkardel } 2839abb0f93cSkardel 2840abb0f93cSkardel 2841abb0f93cSkardel /* 2842abb0f93cSkardel * io_multicast_del() - delete multicast group address 2843abb0f93cSkardel */ 2844abb0f93cSkardel void 2845abb0f93cSkardel io_multicast_del( 2846abb0f93cSkardel sockaddr_u * addr 2847abb0f93cSkardel ) 2848abb0f93cSkardel { 2849abb0f93cSkardel #ifdef MCAST 285045530cf1Skardel endpt *iface; 2851abb0f93cSkardel 2852abb0f93cSkardel /* 2853abb0f93cSkardel * Check to see if this is a multicast address 2854abb0f93cSkardel */ 2855abb0f93cSkardel if (!addr_ismulticast(addr)) { 2856abb0f93cSkardel msyslog(LOG_ERR, "invalid multicast address %s", 2857abb0f93cSkardel stoa(addr)); 2858abb0f93cSkardel return; 2859abb0f93cSkardel } 2860abb0f93cSkardel 2861abb0f93cSkardel /* 2862abb0f93cSkardel * Disable reception of multicast packets 2863abb0f93cSkardel */ 2864abb0f93cSkardel while ((iface = find_flagged_addr_in_list(addr, INT_MCASTOPEN)) 2865abb0f93cSkardel != NULL) 2866abb0f93cSkardel socket_multicast_disable(iface, addr); 2867abb0f93cSkardel 2868abb0f93cSkardel delete_addr_from_list(addr); 2869abb0f93cSkardel 2870abb0f93cSkardel #else /* not MCAST */ 2871abb0f93cSkardel msyslog(LOG_ERR, 2872abb0f93cSkardel "Can not delete multicast address %s: no multicast support", 2873abb0f93cSkardel stoa(addr)); 2874abb0f93cSkardel #endif /* not MCAST */ 2875abb0f93cSkardel } 2876abb0f93cSkardel 2877abb0f93cSkardel 2878abb0f93cSkardel /* 2879abb0f93cSkardel * open_socket - open a socket, returning the file descriptor 2880abb0f93cSkardel */ 2881abb0f93cSkardel 2882abb0f93cSkardel static SOCKET 2883abb0f93cSkardel open_socket( 2884abb0f93cSkardel sockaddr_u * addr, 2885abb0f93cSkardel int bcast, 2886abb0f93cSkardel int turn_off_reuse, 288745530cf1Skardel endpt * interf 2888abb0f93cSkardel ) 2889abb0f93cSkardel { 2890abb0f93cSkardel SOCKET fd; 2891abb0f93cSkardel int errval; 2892abb0f93cSkardel /* 2893abb0f93cSkardel * int is OK for REUSEADR per 2894abb0f93cSkardel * http://www.kohala.com/start/mcast.api.txt 2895abb0f93cSkardel */ 2896abb0f93cSkardel int on = 1; 2897abb0f93cSkardel int off = 0; 2898abb0f93cSkardel 2899abb0f93cSkardel if (IS_IPV6(addr) && !ipv6_works) 2900abb0f93cSkardel return INVALID_SOCKET; 2901abb0f93cSkardel 2902abb0f93cSkardel /* create a datagram (UDP) socket */ 2903abb0f93cSkardel fd = socket(AF(addr), SOCK_DGRAM, 0); 2904abb0f93cSkardel if (INVALID_SOCKET == fd) { 290545530cf1Skardel errval = socket_errno(); 2906abb0f93cSkardel msyslog(LOG_ERR, 2907abb0f93cSkardel "socket(AF_INET%s, SOCK_DGRAM, 0) failed on address %s: %m", 2908abb0f93cSkardel IS_IPV6(addr) ? "6" : "", stoa(addr)); 2909abb0f93cSkardel 2910abb0f93cSkardel if (errval == EPROTONOSUPPORT || 2911abb0f93cSkardel errval == EAFNOSUPPORT || 2912abb0f93cSkardel errval == EPFNOSUPPORT) 2913abb0f93cSkardel return (INVALID_SOCKET); 2914abb0f93cSkardel 2915abb0f93cSkardel errno = errval; 2916abb0f93cSkardel msyslog(LOG_ERR, 2917abb0f93cSkardel "unexpected socket() error %m code %d (not EPROTONOSUPPORT nor EAFNOSUPPORT nor EPFNOSUPPORT) - exiting", 2918abb0f93cSkardel errno); 2919abb0f93cSkardel exit(1); 2920abb0f93cSkardel } 2921abb0f93cSkardel 2922abb0f93cSkardel #ifdef SYS_WINNT 2923abb0f93cSkardel connection_reset_fix(fd, addr); 2924abb0f93cSkardel #endif 2925abb0f93cSkardel /* 2926abb0f93cSkardel * Fixup the file descriptor for some systems 2927abb0f93cSkardel * See bug #530 for details of the issue. 2928abb0f93cSkardel */ 2929abb0f93cSkardel fd = move_fd(fd); 2930abb0f93cSkardel 2931abb0f93cSkardel /* 2932abb0f93cSkardel * set SO_REUSEADDR since we will be binding the same port 2933abb0f93cSkardel * number on each interface according to turn_off_reuse. 2934abb0f93cSkardel * This is undesirable on Windows versions starting with 2935abb0f93cSkardel * Windows XP (numeric version 5.1). 2936abb0f93cSkardel */ 2937abb0f93cSkardel #ifdef SYS_WINNT 2938abb0f93cSkardel if (isc_win32os_versioncheck(5, 1, 0, 0) < 0) /* before 5.1 */ 2939abb0f93cSkardel #endif 2940abb0f93cSkardel if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 2941abb0f93cSkardel (char *)((turn_off_reuse) 2942abb0f93cSkardel ? &off 2943abb0f93cSkardel : &on), 2944abb0f93cSkardel sizeof(on))) { 2945abb0f93cSkardel 2946abb0f93cSkardel msyslog(LOG_ERR, 2947abb0f93cSkardel "setsockopt SO_REUSEADDR %s fails for address %s: %m", 2948abb0f93cSkardel (turn_off_reuse) 2949abb0f93cSkardel ? "off" 2950abb0f93cSkardel : "on", 2951abb0f93cSkardel stoa(addr)); 2952abb0f93cSkardel closesocket(fd); 2953abb0f93cSkardel return INVALID_SOCKET; 2954abb0f93cSkardel } 2955abb0f93cSkardel #ifdef SO_EXCLUSIVEADDRUSE 2956abb0f93cSkardel /* 2957abb0f93cSkardel * setting SO_EXCLUSIVEADDRUSE on the wildcard we open 2958abb0f93cSkardel * first will cause more specific binds to fail. 2959abb0f93cSkardel */ 2960abb0f93cSkardel if (!(interf->flags & INT_WILDCARD)) 2961abb0f93cSkardel set_excladdruse(fd); 2962abb0f93cSkardel #endif 2963abb0f93cSkardel 2964abb0f93cSkardel /* 2965abb0f93cSkardel * IPv4 specific options go here 2966abb0f93cSkardel */ 2967abb0f93cSkardel if (IS_IPV4(addr)) { 2968b3d6264cSchristos #if defined(IPPROTO_IP) && defined(IP_TOS) 2969abb0f93cSkardel if (setsockopt(fd, IPPROTO_IP, IP_TOS, (char*)&qos, 2970abb0f93cSkardel sizeof(qos))) 2971abb0f93cSkardel msyslog(LOG_ERR, 2972abb0f93cSkardel "setsockopt IP_TOS (%02x) fails on address %s: %m", 2973abb0f93cSkardel qos, stoa(addr)); 2974b3d6264cSchristos #endif /* IPPROTO_IP && IP_TOS */ 2975abb0f93cSkardel if (bcast) 2976abb0f93cSkardel socket_broadcast_enable(interf, fd, addr); 2977abb0f93cSkardel } 2978abb0f93cSkardel 2979abb0f93cSkardel /* 2980abb0f93cSkardel * IPv6 specific options go here 2981abb0f93cSkardel */ 2982abb0f93cSkardel if (IS_IPV6(addr)) { 2983b3d6264cSchristos #if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS) 2984b3d6264cSchristos if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, (char*)&qos, 2985b3d6264cSchristos sizeof(qos))) 2986b3d6264cSchristos msyslog(LOG_ERR, 2987b3d6264cSchristos "setsockopt IPV6_TCLASS (%02x) fails on address %s: %m", 2988b3d6264cSchristos qos, stoa(addr)); 2989b3d6264cSchristos #endif /* IPPROTO_IPV6 && IPV6_TCLASS */ 299045530cf1Skardel #ifdef IPV6_V6ONLY 2991abb0f93cSkardel if (isc_net_probe_ipv6only() == ISC_R_SUCCESS 2992abb0f93cSkardel && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, 2993abb0f93cSkardel (char*)&on, sizeof(on))) 2994abb0f93cSkardel msyslog(LOG_ERR, 2995abb0f93cSkardel "setsockopt IPV6_V6ONLY on fails on address %s: %m", 2996abb0f93cSkardel stoa(addr)); 299745530cf1Skardel #endif 299845530cf1Skardel #ifdef IPV6_BINDV6ONLY 2999abb0f93cSkardel if (setsockopt(fd, IPPROTO_IPV6, IPV6_BINDV6ONLY, 3000abb0f93cSkardel (char*)&on, sizeof(on))) 3001abb0f93cSkardel msyslog(LOG_ERR, 3002abb0f93cSkardel "setsockopt IPV6_BINDV6ONLY on fails on address %s: %m", 3003abb0f93cSkardel stoa(addr)); 300445530cf1Skardel #endif 3005abb0f93cSkardel } 3006abb0f93cSkardel 3007abb0f93cSkardel #ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND 3008abb0f93cSkardel /* 3009abb0f93cSkardel * some OSes don't allow binding to more specific 3010abb0f93cSkardel * addresses if a wildcard address already bound 3011abb0f93cSkardel * to the port and SO_REUSEADDR is not set 3012abb0f93cSkardel */ 3013abb0f93cSkardel if (!is_wildcard_addr(addr)) 3014abb0f93cSkardel set_wildcard_reuse(AF(addr), 1); 3015abb0f93cSkardel #endif 3016abb0f93cSkardel 3017abb0f93cSkardel /* 3018abb0f93cSkardel * bind the local address. 3019abb0f93cSkardel */ 3020abb0f93cSkardel errval = bind(fd, &addr->sa, SOCKLEN(addr)); 3021abb0f93cSkardel 3022abb0f93cSkardel #ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND 3023abb0f93cSkardel if (!is_wildcard_addr(addr)) 3024abb0f93cSkardel set_wildcard_reuse(AF(addr), 0); 3025abb0f93cSkardel #endif 3026abb0f93cSkardel 3027abb0f93cSkardel if (errval < 0) { 3028abb0f93cSkardel /* 3029abb0f93cSkardel * Don't log this under all conditions 3030abb0f93cSkardel */ 3031abb0f93cSkardel if (turn_off_reuse == 0 3032abb0f93cSkardel #ifdef DEBUG 3033abb0f93cSkardel || debug > 1 3034abb0f93cSkardel #endif 3035abb0f93cSkardel ) { 3036abb0f93cSkardel msyslog(LOG_ERR, 303724d029faSmlelstv "bind(%d) AF_INET%s %s#%d%s flags 0x%x failed: %m", 3038abb0f93cSkardel fd, IS_IPV6(addr) ? "6" : "", 303924d029faSmlelstv stoa(addr), SRCPORT(addr), 3040abb0f93cSkardel IS_MCAST(addr) ? " (multicast)" : "", 3041abb0f93cSkardel interf->flags); 3042abb0f93cSkardel } 3043abb0f93cSkardel 3044abb0f93cSkardel closesocket(fd); 3045abb0f93cSkardel 3046abb0f93cSkardel return INVALID_SOCKET; 3047abb0f93cSkardel } 3048abb0f93cSkardel 3049abb0f93cSkardel #ifdef HAVE_TIMESTAMP 3050abb0f93cSkardel { 3051abb0f93cSkardel if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, 3052abb0f93cSkardel (char*)&on, sizeof(on))) 3053abb0f93cSkardel msyslog(LOG_DEBUG, 3054abb0f93cSkardel "setsockopt SO_TIMESTAMP on fails on address %s: %m", 3055abb0f93cSkardel stoa(addr)); 3056abb0f93cSkardel else 3057abb0f93cSkardel DPRINTF(4, ("setsockopt SO_TIMESTAMP enabled on fd %d address %s\n", 3058abb0f93cSkardel fd, stoa(addr))); 3059abb0f93cSkardel } 3060abb0f93cSkardel #endif 3061b3d6264cSchristos #ifdef HAVE_TIMESTAMPNS 3062b3d6264cSchristos { 3063b3d6264cSchristos if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPNS, 3064b3d6264cSchristos (char*)&on, sizeof(on))) 3065b3d6264cSchristos msyslog(LOG_DEBUG, 3066b3d6264cSchristos "setsockopt SO_TIMESTAMPNS on fails on address %s: %m", 3067b3d6264cSchristos stoa(addr)); 3068b3d6264cSchristos else 3069b3d6264cSchristos DPRINTF(4, ("setsockopt SO_TIMESTAMPNS enabled on fd %d address %s\n", 3070b3d6264cSchristos fd, stoa(addr))); 3071b3d6264cSchristos } 3072b3d6264cSchristos #endif 3073b3d6264cSchristos #ifdef HAVE_BINTIME 3074b3d6264cSchristos { 3075b3d6264cSchristos if (setsockopt(fd, SOL_SOCKET, SO_BINTIME, 3076b3d6264cSchristos (char*)&on, sizeof(on))) 3077b3d6264cSchristos msyslog(LOG_DEBUG, 3078b3d6264cSchristos "setsockopt SO_BINTIME on fails on address %s: %m", 3079b3d6264cSchristos stoa(addr)); 3080b3d6264cSchristos else 3081b3d6264cSchristos DPRINTF(4, ("setsockopt SO_BINTIME enabled on fd %d address %s\n", 3082b3d6264cSchristos fd, stoa(addr))); 3083b3d6264cSchristos } 3084b3d6264cSchristos #endif 3085b3d6264cSchristos 3086abb0f93cSkardel DPRINTF(4, ("bind(%d) AF_INET%s, addr %s%%%d#%d, flags 0x%x\n", 3087abb0f93cSkardel fd, IS_IPV6(addr) ? "6" : "", stoa(addr), 3088abb0f93cSkardel SCOPE(addr), SRCPORT(addr), interf->flags)); 3089abb0f93cSkardel 3090b3d6264cSchristos make_socket_nonblocking(fd); 3091abb0f93cSkardel 3092abb0f93cSkardel #ifdef HAVE_SIGNALED_IO 3093abb0f93cSkardel init_socket_sig(fd); 3094abb0f93cSkardel #endif /* not HAVE_SIGNALED_IO */ 3095abb0f93cSkardel 3096abb0f93cSkardel add_fd_to_list(fd, FD_TYPE_SOCKET); 3097abb0f93cSkardel 3098abb0f93cSkardel #if !defined(SYS_WINNT) && !defined(VMS) 3099abb0f93cSkardel DPRINTF(4, ("flags for fd %d: 0x%x\n", fd, 3100abb0f93cSkardel fcntl(fd, F_GETFL, 0))); 3101abb0f93cSkardel #endif /* SYS_WINNT || VMS */ 3102abb0f93cSkardel 3103abb0f93cSkardel #if defined(HAVE_IO_COMPLETION_PORT) 3104abb0f93cSkardel /* 3105abb0f93cSkardel * Add the socket to the completion port 3106abb0f93cSkardel */ 3107335f7552Schristos if (!io_completion_port_add_socket(fd, interf, bcast)) { 3108abb0f93cSkardel msyslog(LOG_ERR, "unable to set up io completion port - EXITING"); 3109abb0f93cSkardel exit(1); 3110abb0f93cSkardel } 3111abb0f93cSkardel #endif 3112abb0f93cSkardel return fd; 3113abb0f93cSkardel } 3114abb0f93cSkardel 311545530cf1Skardel 311645530cf1Skardel 3117abb0f93cSkardel /* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */ 3118abb0f93cSkardel /* 3119abb0f93cSkardel * sendpkt - send a packet to the specified destination. Maintain a 3120abb0f93cSkardel * send error cache so that only the first consecutive error for a 3121abb0f93cSkardel * destination is logged. 3122abb0f93cSkardel */ 3123abb0f93cSkardel void 3124abb0f93cSkardel sendpkt( 3125abb0f93cSkardel sockaddr_u * dest, 312645530cf1Skardel struct interface * ep, 3127abb0f93cSkardel int ttl, 3128abb0f93cSkardel struct pkt * pkt, 3129abb0f93cSkardel int len 3130abb0f93cSkardel ) 3131abb0f93cSkardel { 313245530cf1Skardel endpt * src; 313345530cf1Skardel int ismcast; 3134abb0f93cSkardel int cc; 313545530cf1Skardel int rc; 313645530cf1Skardel u_char cttl; 3137abb0f93cSkardel 313845530cf1Skardel ismcast = IS_MCAST(dest); 313945530cf1Skardel if (!ismcast) 314045530cf1Skardel src = ep; 314145530cf1Skardel else 314245530cf1Skardel src = (IS_IPV4(dest)) 314345530cf1Skardel ? mc4_list 314445530cf1Skardel : mc6_list; 314545530cf1Skardel 314645530cf1Skardel if (NULL == src) { 3147abb0f93cSkardel /* 3148abb0f93cSkardel * unbound peer - drop request and wait for better 3149abb0f93cSkardel * network conditions 3150abb0f93cSkardel */ 3151abb0f93cSkardel DPRINTF(2, ("%ssendpkt(dst=%s, ttl=%d, len=%d): no interface - IGNORED\n", 315245530cf1Skardel ismcast ? "\tMCAST\t***** " : "", 3153abb0f93cSkardel stoa(dest), ttl, len)); 3154abb0f93cSkardel return; 3155abb0f93cSkardel } 3156abb0f93cSkardel 315745530cf1Skardel do { 3158abb0f93cSkardel DPRINTF(2, ("%ssendpkt(%d, dst=%s, src=%s, ttl=%d, len=%d)\n", 315945530cf1Skardel ismcast ? "\tMCAST\t***** " : "", src->fd, 316045530cf1Skardel stoa(dest), stoa(&src->sin), ttl, len)); 3161abb0f93cSkardel #ifdef MCAST 3162abb0f93cSkardel /* 3163abb0f93cSkardel * for the moment we use the bcast option to set multicast ttl 3164abb0f93cSkardel */ 316545530cf1Skardel if (ismcast && ttl > 0 && ttl != src->last_ttl) { 3166abb0f93cSkardel /* 3167abb0f93cSkardel * set the multicast ttl for outgoing packets 3168abb0f93cSkardel */ 316945530cf1Skardel switch (AF(&src->sin)) { 3170abb0f93cSkardel 3171abb0f93cSkardel case AF_INET : 3172abb0f93cSkardel cttl = (u_char)ttl; 317345530cf1Skardel rc = setsockopt(src->fd, IPPROTO_IP, 3174abb0f93cSkardel IP_MULTICAST_TTL, 317545530cf1Skardel (void *)&cttl, 317645530cf1Skardel sizeof(cttl)); 3177abb0f93cSkardel break; 3178abb0f93cSkardel 3179abb0f93cSkardel # ifdef INCLUDE_IPV6_SUPPORT 3180abb0f93cSkardel case AF_INET6 : 318145530cf1Skardel rc = setsockopt(src->fd, IPPROTO_IPV6, 3182abb0f93cSkardel IPV6_MULTICAST_HOPS, 318345530cf1Skardel (void *)&ttl, 318445530cf1Skardel sizeof(ttl)); 3185abb0f93cSkardel break; 3186abb0f93cSkardel # endif /* INCLUDE_IPV6_SUPPORT */ 3187abb0f93cSkardel 318845530cf1Skardel default: 318945530cf1Skardel rc = 0; 3190abb0f93cSkardel } 3191abb0f93cSkardel 319245530cf1Skardel if (!rc) 319345530cf1Skardel src->last_ttl = ttl; 3194abb0f93cSkardel else 3195abb0f93cSkardel msyslog(LOG_ERR, 3196abb0f93cSkardel "setsockopt IP_MULTICAST_TTL/IPV6_MULTICAST_HOPS fails on address %s: %m", 319745530cf1Skardel stoa(&src->sin)); 3198abb0f93cSkardel } 3199abb0f93cSkardel #endif /* MCAST */ 3200abb0f93cSkardel 3201abb0f93cSkardel #ifdef SIM 320245530cf1Skardel cc = simulate_server(dest, src, pkt); 3203335f7552Schristos #elif defined(HAVE_IO_COMPLETION_PORT) 3204335f7552Schristos cc = io_completion_port_sendto(src, src->fd, pkt, 3205335f7552Schristos (size_t)len, (sockaddr_u *)&dest->sa); 320645530cf1Skardel #else 320745530cf1Skardel cc = sendto(src->fd, (char *)pkt, (u_int)len, 0, 320845530cf1Skardel &dest->sa, SOCKLEN(dest)); 3209abb0f93cSkardel #endif 321045530cf1Skardel if (cc == -1) { 321145530cf1Skardel src->notsent++; 3212abb0f93cSkardel packets_notsent++; 3213abb0f93cSkardel } else { 321445530cf1Skardel src->sent++; 3215abb0f93cSkardel packets_sent++; 3216abb0f93cSkardel } 321745530cf1Skardel if (ismcast) 321845530cf1Skardel src = src->mclink; 321945530cf1Skardel } while (ismcast && src != NULL); 3220abb0f93cSkardel } 3221abb0f93cSkardel 3222abb0f93cSkardel 3223abb0f93cSkardel #if !defined(HAVE_IO_COMPLETION_PORT) 3224335f7552Schristos #if !defined(HAVE_SIGNALED_IO) 3225abb0f93cSkardel /* 3226abb0f93cSkardel * fdbits - generate ascii representation of fd_set (FAU debug support) 3227abb0f93cSkardel * HFDF format - highest fd first. 3228abb0f93cSkardel */ 3229abb0f93cSkardel static char * 3230abb0f93cSkardel fdbits( 3231abb0f93cSkardel int count, 3232335f7552Schristos const fd_set* set 3233abb0f93cSkardel ) 3234abb0f93cSkardel { 3235abb0f93cSkardel static char buffer[256]; 3236abb0f93cSkardel char * buf = buffer; 3237abb0f93cSkardel 3238abb0f93cSkardel count = min(count, 255); 3239abb0f93cSkardel 3240abb0f93cSkardel while (count >= 0) { 3241abb0f93cSkardel *buf++ = FD_ISSET(count, set) ? '#' : '-'; 3242abb0f93cSkardel count--; 3243abb0f93cSkardel } 3244abb0f93cSkardel *buf = '\0'; 3245abb0f93cSkardel 3246abb0f93cSkardel return buffer; 3247abb0f93cSkardel } 3248335f7552Schristos #endif 3249b3d6264cSchristos 3250b3d6264cSchristos #ifdef REFCLOCK 3251abb0f93cSkardel /* 3252abb0f93cSkardel * Routine to read the refclock packets for a specific interface 3253abb0f93cSkardel * Return the number of bytes read. That way we know if we should 3254abb0f93cSkardel * read it again or go on to the next one if no bytes returned 3255abb0f93cSkardel */ 3256abb0f93cSkardel static inline int 3257b3d6264cSchristos read_refclock_packet( 3258b3d6264cSchristos SOCKET fd, 3259b3d6264cSchristos struct refclockio * rp, 3260b3d6264cSchristos l_fp ts 3261b3d6264cSchristos ) 3262abb0f93cSkardel { 326309f14f80Schristos u_int read_count; 3264abb0f93cSkardel int buflen; 3265b3d6264cSchristos int saved_errno; 3266b3d6264cSchristos int consumed; 3267b3d6264cSchristos struct recvbuf * rb; 3268abb0f93cSkardel 3269abb0f93cSkardel rb = get_free_recv_buffer(); 3270abb0f93cSkardel 3271abb0f93cSkardel if (NULL == rb) { 3272abb0f93cSkardel /* 3273abb0f93cSkardel * No buffer space available - just drop the packet 3274abb0f93cSkardel */ 3275abb0f93cSkardel char buf[RX_BUFF_SIZE]; 3276abb0f93cSkardel 3277abb0f93cSkardel buflen = read(fd, buf, sizeof buf); 3278abb0f93cSkardel packets_dropped++; 3279abb0f93cSkardel return (buflen); 3280abb0f93cSkardel } 3281abb0f93cSkardel 328209f14f80Schristos /* TALOS-CAN-0064: avoid signed/unsigned clashes that can lead 328309f14f80Schristos * to buffer overrun and memory corruption 328409f14f80Schristos */ 328509f14f80Schristos if (rp->datalen <= 0 || (size_t)rp->datalen > sizeof(rb->recv_space)) 328609f14f80Schristos read_count = sizeof(rb->recv_space); 328709f14f80Schristos else 328809f14f80Schristos read_count = (u_int)rp->datalen; 3289b3d6264cSchristos do { 329009f14f80Schristos buflen = read(fd, (char *)&rb->recv_space, read_count); 3291b3d6264cSchristos } while (buflen < 0 && EINTR == errno); 3292abb0f93cSkardel 3293b3d6264cSchristos if (buflen <= 0) { 3294b3d6264cSchristos saved_errno = errno; 3295abb0f93cSkardel freerecvbuf(rb); 3296b3d6264cSchristos errno = saved_errno; 3297b3d6264cSchristos return buflen; 3298abb0f93cSkardel } 3299abb0f93cSkardel 3300abb0f93cSkardel /* 3301abb0f93cSkardel * Got one. Mark how and when it got here, 3302abb0f93cSkardel * put it on the full list and do bookkeeping. 3303abb0f93cSkardel */ 3304abb0f93cSkardel rb->recv_length = buflen; 3305b3d6264cSchristos rb->recv_peer = rp->srcclock; 3306abb0f93cSkardel rb->dstadr = 0; 3307abb0f93cSkardel rb->fd = fd; 3308abb0f93cSkardel rb->recv_time = ts; 3309abb0f93cSkardel rb->receiver = rp->clock_recv; 3310abb0f93cSkardel 3311b3d6264cSchristos consumed = indicate_refclock_packet(rp, rb); 3312b3d6264cSchristos if (!consumed) { 3313abb0f93cSkardel rp->recvcount++; 3314abb0f93cSkardel packets_received++; 3315abb0f93cSkardel } 3316abb0f93cSkardel 3317b3d6264cSchristos return buflen; 3318b3d6264cSchristos } 3319b3d6264cSchristos #endif /* REFCLOCK */ 3320abb0f93cSkardel 3321b3d6264cSchristos 3322b3d6264cSchristos #ifdef HAVE_PACKET_TIMESTAMP 3323abb0f93cSkardel /* 3324abb0f93cSkardel * extract timestamps from control message buffer 3325abb0f93cSkardel */ 3326abb0f93cSkardel static l_fp 3327abb0f93cSkardel fetch_timestamp( 3328abb0f93cSkardel struct recvbuf * rb, 3329abb0f93cSkardel struct msghdr * msghdr, 3330abb0f93cSkardel l_fp ts 3331abb0f93cSkardel ) 3332abb0f93cSkardel { 3333abb0f93cSkardel struct cmsghdr * cmsghdr; 3334b3d6264cSchristos unsigned long ticks; 3335b3d6264cSchristos double fuzz; 3336b3d6264cSchristos l_fp lfpfuzz; 3337b3d6264cSchristos l_fp nts; 3338b3d6264cSchristos #ifdef DEBUG_TIMING 3339b3d6264cSchristos l_fp dts; 3340b3d6264cSchristos #endif 3341abb0f93cSkardel 3342abb0f93cSkardel cmsghdr = CMSG_FIRSTHDR(msghdr); 3343abb0f93cSkardel while (cmsghdr != NULL) { 3344abb0f93cSkardel switch (cmsghdr->cmsg_type) 3345abb0f93cSkardel { 3346b3d6264cSchristos #ifdef HAVE_BINTIME 3347b3d6264cSchristos case SCM_BINTIME: 3348b3d6264cSchristos #endif /* HAVE_BINTIME */ 3349b3d6264cSchristos #ifdef HAVE_TIMESTAMPNS 3350b3d6264cSchristos case SCM_TIMESTAMPNS: 3351b3d6264cSchristos #endif /* HAVE_TIMESTAMPNS */ 3352b3d6264cSchristos #ifdef HAVE_TIMESTAMP 3353abb0f93cSkardel case SCM_TIMESTAMP: 3354b3d6264cSchristos #endif /* HAVE_TIMESTAMP */ 3355b3d6264cSchristos #if defined(HAVE_BINTIME) || defined (HAVE_TIMESTAMPNS) || defined(HAVE_TIMESTAMP) 3356b3d6264cSchristos switch (cmsghdr->cmsg_type) 3357abb0f93cSkardel { 3358b3d6264cSchristos #ifdef HAVE_BINTIME 3359b3d6264cSchristos case SCM_BINTIME: 336066fcc386Schristos { 336166fcc386Schristos struct bintime pbt; 336266fcc386Schristos memcpy(&pbt, CMSG_DATA(cmsghdr), sizeof(pbt)); 3363b3d6264cSchristos /* 3364b3d6264cSchristos * bintime documentation is at http://phk.freebsd.dk/pubs/timecounter.pdf 3365b3d6264cSchristos */ 336666fcc386Schristos nts.l_i = pbt.sec + JAN_1970; 336766fcc386Schristos nts.l_uf = (u_int32)(pbt.frac >> 32); 3368b3d6264cSchristos if (sys_tick > measured_tick && 3369b3d6264cSchristos sys_tick > 1e-9) { 3370b3d6264cSchristos ticks = (unsigned long)(nts.l_uf / (unsigned long)(sys_tick * FRAC)); 3371b3d6264cSchristos nts.l_uf = (unsigned long)(ticks * (unsigned long)(sys_tick * FRAC)); 3372b3d6264cSchristos } 3373b3d6264cSchristos DPRINTF(4, ("fetch_timestamp: system bintime network time stamp: %ld.%09lu\n", 337466fcc386Schristos pbt.sec, (unsigned long)((nts.l_uf / FRAC) * 1e9))); 337566fcc386Schristos } 3376b3d6264cSchristos break; 3377b3d6264cSchristos #endif /* HAVE_BINTIME */ 3378b3d6264cSchristos #ifdef HAVE_TIMESTAMPNS 3379b3d6264cSchristos case SCM_TIMESTAMPNS: 338066fcc386Schristos { 338166fcc386Schristos struct timespec pts; 338266fcc386Schristos memcpy(&pts, CMSG_DATA(cmsghdr), sizeof(pts)); 3383b3d6264cSchristos if (sys_tick > measured_tick && 3384b3d6264cSchristos sys_tick > 1e-9) { 338566fcc386Schristos ticks = (unsigned long)((pts.tv_nsec * 1e-9) / 3386b3d6264cSchristos sys_tick); 338766fcc386Schristos pts.tv_nsec = (long)(ticks * 1e9 * 3388b3d6264cSchristos sys_tick); 3389b3d6264cSchristos } 3390b3d6264cSchristos DPRINTF(4, ("fetch_timestamp: system nsec network time stamp: %ld.%09ld\n", 339166fcc386Schristos pts.tv_sec, pts.tv_nsec)); 339266fcc386Schristos nts = tspec_stamp_to_lfp(pts); 339366fcc386Schristos } 3394b3d6264cSchristos break; 3395b3d6264cSchristos #endif /* HAVE_TIMESTAMPNS */ 3396b3d6264cSchristos #ifdef HAVE_TIMESTAMP 3397b3d6264cSchristos case SCM_TIMESTAMP: 339866fcc386Schristos { 339966fcc386Schristos struct timeval ptv; 340066fcc386Schristos memcpy(&ptv, CMSG_DATA(cmsghdr), sizeof(ptv)); 3401b3d6264cSchristos if (sys_tick > measured_tick && 3402b3d6264cSchristos sys_tick > 1e-6) { 340366fcc386Schristos ticks = (unsigned long)((ptv.tv_usec * 1e-6) / 3404b3d6264cSchristos sys_tick); 340566fcc386Schristos ptv.tv_usec = (long)(ticks * 1e6 * 3406b3d6264cSchristos sys_tick); 3407b3d6264cSchristos } 340874fd00ffSchristos DPRINTF(4, ("fetch_timestamp: system usec network time stamp: %jd.%06ld\n", 340966fcc386Schristos (intmax_t)ptv.tv_sec, (long)ptv.tv_usec)); 341066fcc386Schristos nts = tval_stamp_to_lfp(ptv); 341166fcc386Schristos } 3412b3d6264cSchristos break; 3413b3d6264cSchristos #endif /* HAVE_TIMESTAMP */ 3414b3d6264cSchristos } 3415b3d6264cSchristos fuzz = ntp_random() * 2. / FRAC * sys_fuzz; 3416b3d6264cSchristos DTOLFP(fuzz, &lfpfuzz); 3417b3d6264cSchristos L_ADD(&nts, &lfpfuzz); 3418abb0f93cSkardel #ifdef DEBUG_TIMING 3419abb0f93cSkardel dts = ts; 3420abb0f93cSkardel L_SUB(&dts, &nts); 3421b3d6264cSchristos collect_timing(rb, "input processing delay", 1, 3422b3d6264cSchristos &dts); 3423b3d6264cSchristos DPRINTF(4, ("fetch_timestamp: timestamp delta: %s (incl. fuzz)\n", 3424abb0f93cSkardel lfptoa(&dts, 9))); 3425b3d6264cSchristos #endif /* DEBUG_TIMING */ 3426abb0f93cSkardel ts = nts; /* network time stamp */ 3427abb0f93cSkardel break; 3428b3d6264cSchristos #endif /* HAVE_BINTIME || HAVE_TIMESTAMPNS || HAVE_TIMESTAMP */ 3429b3d6264cSchristos 3430abb0f93cSkardel default: 3431abb0f93cSkardel DPRINTF(4, ("fetch_timestamp: skipping control message 0x%x\n", 3432abb0f93cSkardel cmsghdr->cmsg_type)); 3433abb0f93cSkardel } 3434abb0f93cSkardel cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr); 3435abb0f93cSkardel } 3436abb0f93cSkardel return ts; 3437abb0f93cSkardel } 3438b3d6264cSchristos #endif /* HAVE_PACKET_TIMESTAMP */ 3439abb0f93cSkardel 3440abb0f93cSkardel 3441abb0f93cSkardel /* 3442abb0f93cSkardel * Routine to read the network NTP packets for a specific interface 3443abb0f93cSkardel * Return the number of bytes read. That way we know if we should 3444abb0f93cSkardel * read it again or go on to the next one if no bytes returned 3445abb0f93cSkardel */ 3446abb0f93cSkardel static inline int 3447abb0f93cSkardel read_network_packet( 3448abb0f93cSkardel SOCKET fd, 3449abb0f93cSkardel struct interface * itf, 3450abb0f93cSkardel l_fp ts 3451abb0f93cSkardel ) 3452abb0f93cSkardel { 3453abb0f93cSkardel GETSOCKNAME_SOCKLEN_TYPE fromlen; 3454abb0f93cSkardel int buflen; 3455abb0f93cSkardel register struct recvbuf *rb; 3456b3d6264cSchristos #ifdef HAVE_PACKET_TIMESTAMP 3457abb0f93cSkardel struct msghdr msghdr; 3458abb0f93cSkardel struct iovec iovec; 3459b3d6264cSchristos char control[CMSG_BUFSIZE]; 3460abb0f93cSkardel #endif 3461abb0f93cSkardel 3462abb0f93cSkardel /* 3463abb0f93cSkardel * Get a buffer and read the frame. If we 3464abb0f93cSkardel * haven't got a buffer, or this is received 3465abb0f93cSkardel * on a disallowed socket, just dump the 3466abb0f93cSkardel * packet. 3467abb0f93cSkardel */ 3468abb0f93cSkardel 3469abb0f93cSkardel rb = get_free_recv_buffer(); 3470abb0f93cSkardel if (NULL == rb || itf->ignore_packets) { 3471abb0f93cSkardel char buf[RX_BUFF_SIZE]; 3472abb0f93cSkardel sockaddr_u from; 3473abb0f93cSkardel 3474abb0f93cSkardel if (rb != NULL) 3475abb0f93cSkardel freerecvbuf(rb); 3476abb0f93cSkardel 3477abb0f93cSkardel fromlen = sizeof(from); 3478abb0f93cSkardel buflen = recvfrom(fd, buf, sizeof(buf), 0, 3479abb0f93cSkardel &from.sa, &fromlen); 3480abb0f93cSkardel DPRINTF(4, ("%s on (%lu) fd=%d from %s\n", 3481abb0f93cSkardel (itf->ignore_packets) 3482abb0f93cSkardel ? "ignore" 3483abb0f93cSkardel : "drop", 3484abb0f93cSkardel free_recvbuffs(), fd, stoa(&from))); 3485abb0f93cSkardel if (itf->ignore_packets) 3486abb0f93cSkardel packets_ignored++; 3487abb0f93cSkardel else 3488abb0f93cSkardel packets_dropped++; 3489abb0f93cSkardel return (buflen); 3490abb0f93cSkardel } 3491abb0f93cSkardel 3492abb0f93cSkardel fromlen = sizeof(rb->recv_srcadr); 3493abb0f93cSkardel 3494b3d6264cSchristos #ifndef HAVE_PACKET_TIMESTAMP 3495abb0f93cSkardel rb->recv_length = recvfrom(fd, (char *)&rb->recv_space, 3496abb0f93cSkardel sizeof(rb->recv_space), 0, 3497abb0f93cSkardel &rb->recv_srcadr.sa, &fromlen); 3498abb0f93cSkardel #else 3499abb0f93cSkardel iovec.iov_base = &rb->recv_space; 3500abb0f93cSkardel iovec.iov_len = sizeof(rb->recv_space); 3501abb0f93cSkardel msghdr.msg_name = &rb->recv_srcadr; 3502abb0f93cSkardel msghdr.msg_namelen = fromlen; 3503abb0f93cSkardel msghdr.msg_iov = &iovec; 3504abb0f93cSkardel msghdr.msg_iovlen = 1; 3505abb0f93cSkardel msghdr.msg_control = (void *)&control; 3506abb0f93cSkardel msghdr.msg_controllen = sizeof(control); 3507abb0f93cSkardel msghdr.msg_flags = 0; 3508abb0f93cSkardel rb->recv_length = recvmsg(fd, &msghdr, 0); 3509abb0f93cSkardel #endif 3510abb0f93cSkardel 3511abb0f93cSkardel buflen = rb->recv_length; 3512abb0f93cSkardel 3513abb0f93cSkardel if (buflen == 0 || (buflen == -1 && 3514abb0f93cSkardel (EWOULDBLOCK == errno 3515abb0f93cSkardel #ifdef EAGAIN 3516abb0f93cSkardel || EAGAIN == errno 3517abb0f93cSkardel #endif 3518abb0f93cSkardel ))) { 3519abb0f93cSkardel freerecvbuf(rb); 3520abb0f93cSkardel return (buflen); 3521abb0f93cSkardel } else if (buflen < 0) { 3522abb0f93cSkardel msyslog(LOG_ERR, "recvfrom(%s) fd=%d: %m", 3523abb0f93cSkardel stoa(&rb->recv_srcadr), fd); 3524abb0f93cSkardel DPRINTF(5, ("read_network_packet: fd=%d dropped (bad recvfrom)\n", 3525abb0f93cSkardel fd)); 3526abb0f93cSkardel freerecvbuf(rb); 3527abb0f93cSkardel return (buflen); 3528abb0f93cSkardel } 3529abb0f93cSkardel 3530abb0f93cSkardel DPRINTF(3, ("read_network_packet: fd=%d length %d from %s\n", 3531abb0f93cSkardel fd, buflen, stoa(&rb->recv_srcadr))); 3532abb0f93cSkardel 3533335f7552Schristos #ifdef ENABLE_BUG3020_FIX 3534335f7552Schristos if (ISREFCLOCKADR(&rb->recv_srcadr)) { 3535335f7552Schristos msyslog(LOG_ERR, "recvfrom(%s) fd=%d: refclock srcadr on a network interface!", 3536335f7552Schristos stoa(&rb->recv_srcadr), fd); 3537335f7552Schristos DPRINTF(1, ("read_network_packet: fd=%d dropped (refclock srcadr))\n", 3538335f7552Schristos fd)); 3539335f7552Schristos packets_dropped++; 3540335f7552Schristos freerecvbuf(rb); 3541335f7552Schristos return (buflen); 3542335f7552Schristos } 3543335f7552Schristos #endif 3544335f7552Schristos 3545abb0f93cSkardel /* 3546ad131110Schristos ** Bug 2672: Some OSes (MacOSX and Linux) don't block spoofed ::1 3547ad131110Schristos */ 3548ad131110Schristos 3549ad131110Schristos if (AF_INET6 == itf->family) { 355050cc4415Schristos DPRINTF(2, ("Got an IPv6 packet, from <%s> (%d) to <%s> (%d)\n", 3551ad131110Schristos stoa(&rb->recv_srcadr), 355250cc4415Schristos IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&rb->recv_srcadr)), 3553ad131110Schristos stoa(&itf->sin), 355450cc4415Schristos !IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&itf->sin)) 3555ad131110Schristos )); 3556ad131110Schristos 355750cc4415Schristos if ( IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&rb->recv_srcadr)) 355850cc4415Schristos && !IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&itf->sin)) 3559ad131110Schristos ) { 3560ad131110Schristos packets_dropped++; 356150cc4415Schristos DPRINTF(2, ("DROPPING that packet\n")); 3562ad131110Schristos freerecvbuf(rb); 3563ad131110Schristos return buflen; 3564ad131110Schristos } 356550cc4415Schristos DPRINTF(2, ("processing that packet\n")); 356650cc4415Schristos } 3567ad131110Schristos 3568ad131110Schristos /* 3569abb0f93cSkardel * Got one. Mark how and when it got here, 3570abb0f93cSkardel * put it on the full list and do bookkeeping. 3571abb0f93cSkardel */ 3572abb0f93cSkardel rb->dstadr = itf; 3573abb0f93cSkardel rb->fd = fd; 3574b3d6264cSchristos #ifdef HAVE_PACKET_TIMESTAMP 3575abb0f93cSkardel /* pick up a network time stamp if possible */ 3576abb0f93cSkardel ts = fetch_timestamp(rb, &msghdr, ts); 3577abb0f93cSkardel #endif 3578abb0f93cSkardel rb->recv_time = ts; 3579abb0f93cSkardel rb->receiver = receive; 3580abb0f93cSkardel 3581abb0f93cSkardel add_full_recv_buffer(rb); 3582abb0f93cSkardel 3583abb0f93cSkardel itf->received++; 3584abb0f93cSkardel packets_received++; 3585abb0f93cSkardel return (buflen); 3586abb0f93cSkardel } 3587abb0f93cSkardel 3588b3d6264cSchristos /* 3589b3d6264cSchristos * attempt to handle io (select()/signaled IO) 3590b3d6264cSchristos */ 3591b3d6264cSchristos void 3592b3d6264cSchristos io_handler(void) 3593b3d6264cSchristos { 3594b3d6264cSchristos # ifndef HAVE_SIGNALED_IO 3595b3d6264cSchristos fd_set rdfdes; 3596b3d6264cSchristos int nfound; 3597b3d6264cSchristos 3598b3d6264cSchristos /* 3599b3d6264cSchristos * Use select() on all on all input fd's for unlimited 3600b3d6264cSchristos * time. select() will terminate on SIGALARM or on the 3601b3d6264cSchristos * reception of input. Using select() means we can't do 3602b3d6264cSchristos * robust signal handling and we get a potential race 3603b3d6264cSchristos * between checking for alarms and doing the select(). 3604b3d6264cSchristos * Mostly harmless, I think. 3605b3d6264cSchristos */ 3606b3d6264cSchristos /* 3607b3d6264cSchristos * On VMS, I suspect that select() can't be interrupted 3608b3d6264cSchristos * by a "signal" either, so I take the easy way out and 3609b3d6264cSchristos * have select() time out after one second. 3610b3d6264cSchristos * System clock updates really aren't time-critical, 3611b3d6264cSchristos * and - lacking a hardware reference clock - I have 3612b3d6264cSchristos * yet to learn about anything else that is. 3613b3d6264cSchristos */ 3614335f7552Schristos ++handler_calls; 3615b3d6264cSchristos rdfdes = activefds; 3616b3d6264cSchristos # if !defined(VMS) && !defined(SYS_VXWORKS) 3617b3d6264cSchristos nfound = select(maxactivefd + 1, &rdfdes, NULL, 3618b3d6264cSchristos NULL, NULL); 3619b3d6264cSchristos # else /* VMS, VxWorks */ 3620b3d6264cSchristos /* make select() wake up after one second */ 3621b3d6264cSchristos { 3622b3d6264cSchristos struct timeval t1; 3623b3d6264cSchristos t1.tv_sec = 1; 3624b3d6264cSchristos t1.tv_usec = 0; 3625b3d6264cSchristos nfound = select(maxactivefd + 1, 3626b3d6264cSchristos &rdfdes, NULL, NULL, 3627b3d6264cSchristos &t1); 3628b3d6264cSchristos } 3629b3d6264cSchristos # endif /* VMS, VxWorks */ 3630335f7552Schristos if (nfound < 0 && sanitize_fdset(errno)) { 3631335f7552Schristos struct timeval t1; 3632335f7552Schristos t1.tv_sec = 0; 3633335f7552Schristos t1.tv_usec = 0; 3634335f7552Schristos rdfdes = activefds; 3635335f7552Schristos nfound = select(maxactivefd + 1, 3636335f7552Schristos &rdfdes, NULL, NULL, 3637335f7552Schristos &t1); 3638335f7552Schristos } 3639335f7552Schristos 3640b3d6264cSchristos if (nfound > 0) { 3641b3d6264cSchristos l_fp ts; 3642b3d6264cSchristos 3643b3d6264cSchristos get_systime(&ts); 3644b3d6264cSchristos 3645335f7552Schristos input_handler_scan(&ts, &rdfdes); 3646b3d6264cSchristos } else if (nfound == -1 && errno != EINTR) { 3647b3d6264cSchristos msyslog(LOG_ERR, "select() error: %m"); 3648b3d6264cSchristos } 3649b3d6264cSchristos # ifdef DEBUG 3650b3d6264cSchristos else if (debug > 4) { 3651b3d6264cSchristos msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound); 3652b3d6264cSchristos } else { 36534e3b3909Schristos DPRINTF(3, ("select() returned %d: %m\n", nfound)); 3654b3d6264cSchristos } 3655b3d6264cSchristos # endif /* DEBUG */ 3656b3d6264cSchristos # else /* HAVE_SIGNALED_IO */ 3657b3d6264cSchristos wait_for_signal(); 3658b3d6264cSchristos # endif /* HAVE_SIGNALED_IO */ 3659b3d6264cSchristos } 3660abb0f93cSkardel 3661335f7552Schristos #ifdef HAVE_SIGNALED_IO 3662abb0f93cSkardel /* 3663abb0f93cSkardel * input_handler - receive packets asynchronously 3664335f7552Schristos * 3665335f7552Schristos * ALWAYS IN SIGNAL HANDLER CONTEXT -- only async-safe functions allowed! 3666abb0f93cSkardel */ 3667335f7552Schristos static RETSIGTYPE 3668abb0f93cSkardel input_handler( 3669abb0f93cSkardel l_fp * cts 3670abb0f93cSkardel ) 3671abb0f93cSkardel { 3672abb0f93cSkardel int n; 3673335f7552Schristos struct timeval tvzero; 3674335f7552Schristos fd_set fds; 3675335f7552Schristos 3676335f7552Schristos ++handler_calls; 3677335f7552Schristos 3678335f7552Schristos /* 3679335f7552Schristos * Do a poll to see who has data 3680335f7552Schristos */ 3681335f7552Schristos 3682335f7552Schristos fds = activefds; 3683335f7552Schristos tvzero.tv_sec = tvzero.tv_usec = 0; 3684335f7552Schristos 3685335f7552Schristos n = select(maxactivefd + 1, &fds, NULL, NULL, &tvzero); 3686335f7552Schristos if (n < 0 && sanitize_fdset(errno)) { 3687335f7552Schristos fds = activefds; 3688335f7552Schristos tvzero.tv_sec = tvzero.tv_usec = 0; 3689335f7552Schristos n = select(maxactivefd + 1, &fds, NULL, NULL, &tvzero); 3690335f7552Schristos } 3691335f7552Schristos if (n > 0) 3692335f7552Schristos input_handler_scan(cts, &fds); 3693335f7552Schristos } 3694335f7552Schristos #endif /* HAVE_SIGNALED_IO */ 3695335f7552Schristos 3696335f7552Schristos 3697335f7552Schristos /* 3698335f7552Schristos * Try to sanitize the global FD set 3699335f7552Schristos * 3700335f7552Schristos * SIGNAL HANDLER CONTEXT if HAVE_SIGNALED_IO, ordinary userspace otherwise 3701335f7552Schristos */ 3702335f7552Schristos static int/*BOOL*/ 3703335f7552Schristos sanitize_fdset( 3704335f7552Schristos int errc 3705335f7552Schristos ) 3706335f7552Schristos { 3707335f7552Schristos int j, b, maxscan; 3708335f7552Schristos 3709335f7552Schristos # ifndef HAVE_SIGNALED_IO 3710335f7552Schristos /* 3711335f7552Schristos * extended FAU debugging output 3712335f7552Schristos */ 3713335f7552Schristos if (errc != EINTR) { 3714335f7552Schristos msyslog(LOG_ERR, 3715335f7552Schristos "select(%d, %s, 0L, 0L, &0.0) error: %m", 3716335f7552Schristos maxactivefd + 1, 3717335f7552Schristos fdbits(maxactivefd, &activefds)); 3718335f7552Schristos } 3719335f7552Schristos # endif 3720335f7552Schristos 3721335f7552Schristos if (errc != EBADF) 3722335f7552Schristos return FALSE; 3723335f7552Schristos 3724335f7552Schristos /* if we have oviously bad FDs, try to sanitize the FD set. */ 3725335f7552Schristos for (j = 0, maxscan = 0; j <= maxactivefd; j++) { 3726335f7552Schristos if (FD_ISSET(j, &activefds)) { 3727335f7552Schristos if (-1 != read(j, &b, 0)) { 3728335f7552Schristos maxscan = j; 3729335f7552Schristos continue; 3730335f7552Schristos } 3731335f7552Schristos # ifndef HAVE_SIGNALED_IO 3732335f7552Schristos msyslog(LOG_ERR, 3733335f7552Schristos "Removing bad file descriptor %d from select set", 3734335f7552Schristos j); 3735335f7552Schristos # endif 3736335f7552Schristos FD_CLR(j, &activefds); 3737335f7552Schristos } 3738335f7552Schristos } 3739335f7552Schristos if (maxactivefd != maxscan) 3740335f7552Schristos maxactivefd = maxscan; 3741335f7552Schristos return TRUE; 3742335f7552Schristos } 3743335f7552Schristos 3744335f7552Schristos /* 3745335f7552Schristos * scan the known FDs (clocks, servers, ...) for presence in a 'fd_set'. 3746335f7552Schristos * 3747335f7552Schristos * SIGNAL HANDLER CONTEXT if HAVE_SIGNALED_IO, ordinary userspace otherwise 3748335f7552Schristos */ 3749335f7552Schristos static void 3750335f7552Schristos input_handler_scan( 3751335f7552Schristos const l_fp * cts, 3752335f7552Schristos const fd_set * pfds 3753335f7552Schristos ) 3754335f7552Schristos { 3755335f7552Schristos int buflen; 3756b3d6264cSchristos u_int idx; 3757abb0f93cSkardel int doing; 3758abb0f93cSkardel SOCKET fd; 3759b3d6264cSchristos blocking_child *c; 3760abb0f93cSkardel l_fp ts; /* Timestamp at BOselect() gob */ 3761335f7552Schristos 3762335f7552Schristos #if defined(DEBUG_TIMING) 3763abb0f93cSkardel l_fp ts_e; /* Timestamp at EOselect() gob */ 3764abb0f93cSkardel #endif 376545530cf1Skardel endpt * ep; 3766b3d6264cSchristos #ifdef REFCLOCK 3767b3d6264cSchristos struct refclockio *rp; 3768b3d6264cSchristos int saved_errno; 3769b3d6264cSchristos const char * clk; 3770b3d6264cSchristos #endif 3771b3d6264cSchristos #ifdef HAS_ROUTING_SOCKET 3772abb0f93cSkardel struct asyncio_reader * asyncio_reader; 3773b3d6264cSchristos struct asyncio_reader * next_asyncio_reader; 3774abb0f93cSkardel #endif 3775abb0f93cSkardel 3776abb0f93cSkardel ++handler_pkts; 3777335f7552Schristos ts = *cts; 3778abb0f93cSkardel 3779abb0f93cSkardel #ifdef REFCLOCK 3780abb0f93cSkardel /* 3781abb0f93cSkardel * Check out the reference clocks first, if any 3782abb0f93cSkardel */ 3783abb0f93cSkardel 3784abb0f93cSkardel for (rp = refio; rp != NULL; rp = rp->next) { 3785abb0f93cSkardel fd = rp->fd; 3786abb0f93cSkardel 3787335f7552Schristos if (!FD_ISSET(fd, pfds)) 3788b3d6264cSchristos continue; 3789b3d6264cSchristos buflen = read_refclock_packet(fd, rp, ts); 3790b3d6264cSchristos /* 3791335f7552Schristos * The first read must succeed after select() indicates 3792335f7552Schristos * readability, or we've reached a permanent EOF. 3793335f7552Schristos * http://bugs.ntp.org/1732 reported ntpd munching CPU 3794335f7552Schristos * after a USB GPS was unplugged because select was 3795335f7552Schristos * indicating EOF but ntpd didn't remove the descriptor 3796b3d6264cSchristos * from the activefds set. 3797b3d6264cSchristos */ 3798b3d6264cSchristos if (buflen < 0 && EAGAIN != errno) { 3799b3d6264cSchristos saved_errno = errno; 3800b3d6264cSchristos clk = refnumtoa(&rp->srcclock->srcadr); 3801b3d6264cSchristos errno = saved_errno; 3802b3d6264cSchristos msyslog(LOG_ERR, "%s read: %m", clk); 3803b3d6264cSchristos maintain_activefds(fd, TRUE); 3804b3d6264cSchristos } else if (0 == buflen) { 3805b3d6264cSchristos clk = refnumtoa(&rp->srcclock->srcadr); 3806b3d6264cSchristos msyslog(LOG_ERR, "%s read EOF", clk); 3807b3d6264cSchristos maintain_activefds(fd, TRUE); 3808b3d6264cSchristos } else { 3809b3d6264cSchristos /* drain any remaining refclock input */ 3810b3d6264cSchristos do { 3811b3d6264cSchristos buflen = read_refclock_packet(fd, rp, ts); 3812abb0f93cSkardel } while (buflen > 0); 3813abb0f93cSkardel } 3814abb0f93cSkardel } 3815abb0f93cSkardel #endif /* REFCLOCK */ 3816abb0f93cSkardel 3817abb0f93cSkardel /* 3818abb0f93cSkardel * Loop through the interfaces looking for data to read. 3819abb0f93cSkardel */ 382045530cf1Skardel for (ep = ep_list; ep != NULL; ep = ep->elink) { 382145530cf1Skardel for (doing = 0; doing < 2; doing++) { 382245530cf1Skardel if (!doing) { 382345530cf1Skardel fd = ep->fd; 382445530cf1Skardel } else { 382545530cf1Skardel if (!(ep->flags & INT_BCASTOPEN)) 3826abb0f93cSkardel break; 382745530cf1Skardel fd = ep->bfd; 3828abb0f93cSkardel } 3829abb0f93cSkardel if (fd < 0) 3830abb0f93cSkardel continue; 3831335f7552Schristos if (FD_ISSET(fd, pfds)) 3832abb0f93cSkardel do { 3833abb0f93cSkardel buflen = read_network_packet( 383445530cf1Skardel fd, ep, ts); 3835abb0f93cSkardel } while (buflen > 0); 3836abb0f93cSkardel /* Check more interfaces */ 3837abb0f93cSkardel } 3838abb0f93cSkardel } 3839abb0f93cSkardel 3840abb0f93cSkardel #ifdef HAS_ROUTING_SOCKET 3841abb0f93cSkardel /* 3842abb0f93cSkardel * scan list of asyncio readers - currently only used for routing sockets 3843abb0f93cSkardel */ 3844abb0f93cSkardel asyncio_reader = asyncio_reader_list; 3845abb0f93cSkardel 3846abb0f93cSkardel while (asyncio_reader != NULL) { 3847b3d6264cSchristos /* callback may unlink and free asyncio_reader */ 3848b3d6264cSchristos next_asyncio_reader = asyncio_reader->link; 3849335f7552Schristos if (FD_ISSET(asyncio_reader->fd, pfds)) 3850b3d6264cSchristos (*asyncio_reader->receiver)(asyncio_reader); 3851b3d6264cSchristos asyncio_reader = next_asyncio_reader; 3852abb0f93cSkardel } 3853abb0f93cSkardel #endif /* HAS_ROUTING_SOCKET */ 3854abb0f93cSkardel 3855abb0f93cSkardel /* 3856b3d6264cSchristos * Check for a response from a blocking child 3857abb0f93cSkardel */ 3858b3d6264cSchristos for (idx = 0; idx < blocking_children_alloc; idx++) { 3859b3d6264cSchristos c = blocking_children[idx]; 3860b3d6264cSchristos if (NULL == c || -1 == c->resp_read_pipe) 3861b3d6264cSchristos continue; 3862335f7552Schristos if (FD_ISSET(c->resp_read_pipe, pfds)) { 3863335f7552Schristos ++c->resp_ready_seen; 3864335f7552Schristos ++blocking_child_ready_seen; 3865b3d6264cSchristos } 3866b3d6264cSchristos } 3867abb0f93cSkardel 3868abb0f93cSkardel /* We've done our work */ 3869335f7552Schristos #if defined(DEBUG_TIMING) 3870abb0f93cSkardel get_systime(&ts_e); 3871abb0f93cSkardel /* 3872abb0f93cSkardel * (ts_e - ts) is the amount of time we spent 3873abb0f93cSkardel * processing this gob of file descriptors. Log 3874abb0f93cSkardel * it. 3875abb0f93cSkardel */ 3876abb0f93cSkardel L_SUB(&ts_e, &ts); 3877abb0f93cSkardel collect_timing(NULL, "input handler", 1, &ts_e); 3878abb0f93cSkardel if (debug > 3) 3879abb0f93cSkardel msyslog(LOG_DEBUG, 3880abb0f93cSkardel "input_handler: Processed a gob of fd's in %s msec", 3881abb0f93cSkardel lfptoms(&ts_e, 6)); 3882b3d6264cSchristos #endif /* DEBUG_TIMING */ 3883abb0f93cSkardel } 3884b3d6264cSchristos #endif /* !HAVE_IO_COMPLETION_PORT */ 3885b3d6264cSchristos 3886b3d6264cSchristos /* 3887b3d6264cSchristos * find an interface suitable for the src address 3888b3d6264cSchristos */ 3889b3d6264cSchristos endpt * 3890b3d6264cSchristos select_peerinterface( 3891b3d6264cSchristos struct peer * peer, 3892b3d6264cSchristos sockaddr_u * srcadr, 3893b3d6264cSchristos endpt * dstadr 3894b3d6264cSchristos ) 3895b3d6264cSchristos { 3896b3d6264cSchristos endpt *ep; 3897b3d6264cSchristos #ifndef SIM 3898b3d6264cSchristos endpt *wild; 3899b3d6264cSchristos 3900b3d6264cSchristos wild = ANY_INTERFACE_CHOOSE(srcadr); 3901b3d6264cSchristos 3902b3d6264cSchristos /* 3903b3d6264cSchristos * Initialize the peer structure and dance the interface jig. 3904b3d6264cSchristos * Reference clocks step the loopback waltz, the others 3905b3d6264cSchristos * squaredance around the interface list looking for a buddy. If 3906b3d6264cSchristos * the dance peters out, there is always the wildcard interface. 3907b3d6264cSchristos * This might happen in some systems and would preclude proper 3908b3d6264cSchristos * operation with public key cryptography. 3909b3d6264cSchristos */ 3910b3d6264cSchristos if (ISREFCLOCKADR(srcadr)) { 3911b3d6264cSchristos ep = loopback_interface; 3912b3d6264cSchristos } else if (peer->cast_flags & 3913b3d6264cSchristos (MDF_BCLNT | MDF_ACAST | MDF_MCAST | MDF_BCAST)) { 3914b3d6264cSchristos ep = findbcastinter(srcadr); 3915b3d6264cSchristos if (ep != NULL) 3916b3d6264cSchristos DPRINTF(4, ("Found *-cast interface %s for address %s\n", 3917b3d6264cSchristos stoa(&ep->sin), stoa(srcadr))); 3918b3d6264cSchristos else 3919b3d6264cSchristos DPRINTF(4, ("No *-cast local address found for address %s\n", 3920b3d6264cSchristos stoa(srcadr))); 3921b3d6264cSchristos } else { 3922b3d6264cSchristos ep = dstadr; 3923b3d6264cSchristos if (NULL == ep) 3924b3d6264cSchristos ep = wild; 3925b3d6264cSchristos } 3926b3d6264cSchristos /* 3927b3d6264cSchristos * If it is a multicast address, findbcastinter() may not find 3928b3d6264cSchristos * it. For unicast, we get to find the interface when dstadr is 3929b3d6264cSchristos * given to us as the wildcard (ANY_INTERFACE_CHOOSE). Either 3930b3d6264cSchristos * way, try a little harder. 3931b3d6264cSchristos */ 3932b3d6264cSchristos if (wild == ep) 3933b3d6264cSchristos ep = findinterface(srcadr); 3934b3d6264cSchristos /* 3935b3d6264cSchristos * we do not bind to the wildcard interfaces for output 3936b3d6264cSchristos * as our (network) source address would be undefined and 3937b3d6264cSchristos * crypto will not work without knowing the own transmit address 3938b3d6264cSchristos */ 3939b3d6264cSchristos if (ep != NULL && INT_WILDCARD & ep->flags) 3940b3d6264cSchristos if (!accept_wildcard_if_for_winnt) 3941b3d6264cSchristos ep = NULL; 3942b3d6264cSchristos #else /* SIM follows */ 3943b3d6264cSchristos ep = loopback_interface; 3944abb0f93cSkardel #endif 3945abb0f93cSkardel 3946b3d6264cSchristos return ep; 3947b3d6264cSchristos } 3948b3d6264cSchristos 3949b3d6264cSchristos 3950abb0f93cSkardel /* 3951abb0f93cSkardel * findinterface - find local interface corresponding to address 3952abb0f93cSkardel */ 395345530cf1Skardel endpt * 3954abb0f93cSkardel findinterface( 3955abb0f93cSkardel sockaddr_u *addr 3956abb0f93cSkardel ) 3957abb0f93cSkardel { 395845530cf1Skardel endpt *iface; 3959abb0f93cSkardel 3960abb0f93cSkardel iface = findlocalinterface(addr, INT_WILDCARD, 0); 3961abb0f93cSkardel 3962abb0f93cSkardel if (NULL == iface) { 3963abb0f93cSkardel DPRINTF(4, ("Found no interface for address %s - returning wildcard\n", 3964abb0f93cSkardel stoa(addr))); 3965abb0f93cSkardel 3966abb0f93cSkardel iface = ANY_INTERFACE_CHOOSE(addr); 3967abb0f93cSkardel } else 3968abb0f93cSkardel DPRINTF(4, ("Found interface #%d %s for address %s\n", 3969abb0f93cSkardel iface->ifnum, iface->name, stoa(addr))); 3970abb0f93cSkardel 3971abb0f93cSkardel return iface; 3972abb0f93cSkardel } 3973abb0f93cSkardel 3974abb0f93cSkardel /* 3975abb0f93cSkardel * findlocalinterface - find local interface corresponding to addr, 3976abb0f93cSkardel * which does not have any of flags set. If bast is nonzero, addr is 3977abb0f93cSkardel * a broadcast address. 3978abb0f93cSkardel * 3979abb0f93cSkardel * This code attempts to find the local sending address for an outgoing 3980abb0f93cSkardel * address by connecting a new socket to destinationaddress:NTP_PORT 3981abb0f93cSkardel * and reading the sockname of the resulting connect. 3982abb0f93cSkardel * the complicated sequence simulates the routing table lookup 3983abb0f93cSkardel * for to first hop without duplicating any of the routing logic into 3984abb0f93cSkardel * ntpd. preferably we would have used an API call - but its not there - 3985abb0f93cSkardel * so this is the best we can do here short of duplicating to entire routing 3986abb0f93cSkardel * logic in ntpd which would be a silly and really unportable thing to do. 3987abb0f93cSkardel * 3988abb0f93cSkardel */ 398945530cf1Skardel static endpt * 3990abb0f93cSkardel findlocalinterface( 3991abb0f93cSkardel sockaddr_u * addr, 3992abb0f93cSkardel int flags, 3993abb0f93cSkardel int bcast 3994abb0f93cSkardel ) 3995abb0f93cSkardel { 3996abb0f93cSkardel GETSOCKNAME_SOCKLEN_TYPE sockaddrlen; 399745530cf1Skardel endpt * iface; 3998abb0f93cSkardel sockaddr_u saddr; 3999abb0f93cSkardel SOCKET s; 4000abb0f93cSkardel int rtn; 4001abb0f93cSkardel int on; 4002abb0f93cSkardel 4003abb0f93cSkardel DPRINTF(4, ("Finding interface for addr %s in list of addresses\n", 4004abb0f93cSkardel stoa(addr))); 4005abb0f93cSkardel 4006abb0f93cSkardel s = socket(AF(addr), SOCK_DGRAM, 0); 4007abb0f93cSkardel if (INVALID_SOCKET == s) 4008abb0f93cSkardel return NULL; 4009abb0f93cSkardel 4010abb0f93cSkardel /* 4011abb0f93cSkardel * If we are looking for broadcast interface we need to set this 4012abb0f93cSkardel * socket to allow broadcast 4013abb0f93cSkardel */ 4014abb0f93cSkardel if (bcast) { 4015abb0f93cSkardel on = 1; 4016b3d6264cSchristos if (SOCKET_ERROR == setsockopt(s, SOL_SOCKET, 4017b3d6264cSchristos SO_BROADCAST, 4018b3d6264cSchristos (char *)&on, 4019b3d6264cSchristos sizeof(on))) { 4020b3d6264cSchristos closesocket(s); 4021b3d6264cSchristos return NULL; 4022b3d6264cSchristos } 4023abb0f93cSkardel } 4024abb0f93cSkardel 4025abb0f93cSkardel rtn = connect(s, &addr->sa, SOCKLEN(addr)); 4026abb0f93cSkardel if (SOCKET_ERROR == rtn) { 4027abb0f93cSkardel closesocket(s); 4028abb0f93cSkardel return NULL; 4029abb0f93cSkardel } 4030abb0f93cSkardel 4031abb0f93cSkardel sockaddrlen = sizeof(saddr); 4032abb0f93cSkardel rtn = getsockname(s, &saddr.sa, &sockaddrlen); 4033abb0f93cSkardel closesocket(s); 4034abb0f93cSkardel if (SOCKET_ERROR == rtn) 4035abb0f93cSkardel return NULL; 4036abb0f93cSkardel 4037abb0f93cSkardel DPRINTF(4, ("findlocalinterface: kernel maps %s to %s\n", 4038abb0f93cSkardel stoa(addr), stoa(&saddr))); 4039abb0f93cSkardel 4040abb0f93cSkardel iface = getinterface(&saddr, flags); 4041abb0f93cSkardel 4042abb0f93cSkardel /* 404345530cf1Skardel * if we didn't find an exact match on saddr, find the closest 404445530cf1Skardel * available local address. This handles the case of the 404545530cf1Skardel * address suggested by the kernel being excluded by nic rules 404645530cf1Skardel * or the user's -I and -L options to ntpd. 404745530cf1Skardel * See http://bugs.ntp.org/1184 and http://bugs.ntp.org/1683 404845530cf1Skardel * for more background. 4049abb0f93cSkardel */ 4050abb0f93cSkardel if (NULL == iface || iface->ignore_packets) 405145530cf1Skardel iface = findclosestinterface(&saddr, 405245530cf1Skardel flags | INT_LOOPBACK); 4053abb0f93cSkardel 4054abb0f93cSkardel /* Don't use an interface which will ignore replies */ 4055abb0f93cSkardel if (iface != NULL && iface->ignore_packets) 4056abb0f93cSkardel iface = NULL; 4057abb0f93cSkardel 4058abb0f93cSkardel return iface; 4059abb0f93cSkardel } 4060abb0f93cSkardel 4061abb0f93cSkardel 4062abb0f93cSkardel /* 406345530cf1Skardel * findclosestinterface 406445530cf1Skardel * 406545530cf1Skardel * If there are -I/--interface or -L/novirtualips command-line options, 406645530cf1Skardel * or "nic" or "interface" rules in ntp.conf, findlocalinterface() may 406745530cf1Skardel * find the kernel's preferred local address for a given peer address is 406845530cf1Skardel * administratively unavailable to ntpd, and punt to this routine's more 406945530cf1Skardel * expensive search. 407045530cf1Skardel * 407145530cf1Skardel * Find the numerically closest local address to the one connect() 407245530cf1Skardel * suggested. This matches an address on the same subnet first, as 407345530cf1Skardel * needed by Bug 1184, and provides a consistent choice if there are 407445530cf1Skardel * multiple feasible local addresses, regardless of the order ntpd 407545530cf1Skardel * enumerated them. 4076abb0f93cSkardel */ 4077b3d6264cSchristos endpt * 407845530cf1Skardel findclosestinterface( 4079abb0f93cSkardel sockaddr_u * addr, 4080abb0f93cSkardel int flags 4081abb0f93cSkardel ) 4082abb0f93cSkardel { 408345530cf1Skardel endpt * ep; 408445530cf1Skardel endpt * winner; 408545530cf1Skardel sockaddr_u addr_dist; 408645530cf1Skardel sockaddr_u min_dist; 408745530cf1Skardel 4088b3d6264cSchristos ZERO_SOCK(&min_dist); 408945530cf1Skardel winner = NULL; 409045530cf1Skardel 409145530cf1Skardel for (ep = ep_list; ep != NULL; ep = ep->elink) { 409245530cf1Skardel if (ep->ignore_packets || 409345530cf1Skardel AF(addr) != ep->family || 409445530cf1Skardel flags & ep->flags) 409545530cf1Skardel continue; 409645530cf1Skardel 409745530cf1Skardel calc_addr_distance(&addr_dist, addr, &ep->sin); 409845530cf1Skardel if (NULL == winner || 409945530cf1Skardel -1 == cmp_addr_distance(&addr_dist, &min_dist)) { 410045530cf1Skardel min_dist = addr_dist; 410145530cf1Skardel winner = ep; 410245530cf1Skardel } 410345530cf1Skardel } 410445530cf1Skardel if (NULL == winner) 410545530cf1Skardel DPRINTF(4, ("findclosestinterface(%s) failed\n", 410645530cf1Skardel stoa(addr))); 410745530cf1Skardel else 410845530cf1Skardel DPRINTF(4, ("findclosestinterface(%s) -> %s\n", 410945530cf1Skardel stoa(addr), stoa(&winner->sin))); 411045530cf1Skardel 411145530cf1Skardel return winner; 411245530cf1Skardel } 411345530cf1Skardel 411445530cf1Skardel 411545530cf1Skardel /* 411645530cf1Skardel * calc_addr_distance - calculate the distance between two addresses, 411745530cf1Skardel * the absolute value of the difference between 411845530cf1Skardel * the addresses numerically, stored as an address. 411945530cf1Skardel */ 412045530cf1Skardel static void 412145530cf1Skardel calc_addr_distance( 412245530cf1Skardel sockaddr_u * dist, 412345530cf1Skardel const sockaddr_u * a1, 412445530cf1Skardel const sockaddr_u * a2 412545530cf1Skardel ) 412645530cf1Skardel { 412745530cf1Skardel u_int32 a1val; 412845530cf1Skardel u_int32 a2val; 412945530cf1Skardel u_int32 v4dist; 413045530cf1Skardel int found_greater; 413145530cf1Skardel int a1_greater; 413245530cf1Skardel int i; 413345530cf1Skardel 413409f14f80Schristos REQUIRE(AF(a1) == AF(a2)); 413545530cf1Skardel 4136b3d6264cSchristos ZERO_SOCK(dist); 413745530cf1Skardel AF(dist) = AF(a1); 413845530cf1Skardel 413945530cf1Skardel /* v4 can be done a bit simpler */ 414045530cf1Skardel if (IS_IPV4(a1)) { 414145530cf1Skardel a1val = SRCADR(a1); 414245530cf1Skardel a2val = SRCADR(a2); 414345530cf1Skardel v4dist = (a1val > a2val) 414445530cf1Skardel ? a1val - a2val 414545530cf1Skardel : a2val - a1val; 414645530cf1Skardel SET_ADDR4(dist, v4dist); 414745530cf1Skardel 414845530cf1Skardel return; 414945530cf1Skardel } 415045530cf1Skardel 415145530cf1Skardel found_greater = FALSE; 415245530cf1Skardel a1_greater = FALSE; /* suppress pot. uninit. warning */ 4153f40817b7Skardel for (i = 0; i < (int)sizeof(NSRCADR6(a1)); i++) { 415445530cf1Skardel if (!found_greater && 415545530cf1Skardel NSRCADR6(a1)[i] != NSRCADR6(a2)[i]) { 415645530cf1Skardel found_greater = TRUE; 415745530cf1Skardel a1_greater = (NSRCADR6(a1)[i] > NSRCADR6(a2)[i]); 415845530cf1Skardel } 415945530cf1Skardel if (!found_greater) { 416045530cf1Skardel NSRCADR6(dist)[i] = 0; 416145530cf1Skardel } else { 416245530cf1Skardel if (a1_greater) 416345530cf1Skardel NSRCADR6(dist)[i] = NSRCADR6(a1)[i] - 416445530cf1Skardel NSRCADR6(a2)[i]; 416545530cf1Skardel else 416645530cf1Skardel NSRCADR6(dist)[i] = NSRCADR6(a2)[i] - 416745530cf1Skardel NSRCADR6(a1)[i]; 416845530cf1Skardel } 416945530cf1Skardel } 417045530cf1Skardel } 417145530cf1Skardel 417245530cf1Skardel 417345530cf1Skardel /* 417445530cf1Skardel * cmp_addr_distance - compare two address distances, returning -1, 0, 417545530cf1Skardel * 1 to indicate their relationship. 417645530cf1Skardel */ 417745530cf1Skardel static int 417845530cf1Skardel cmp_addr_distance( 417945530cf1Skardel const sockaddr_u * d1, 418045530cf1Skardel const sockaddr_u * d2 418145530cf1Skardel ) 418245530cf1Skardel { 418345530cf1Skardel int i; 418445530cf1Skardel 418509f14f80Schristos REQUIRE(AF(d1) == AF(d2)); 418645530cf1Skardel 418745530cf1Skardel if (IS_IPV4(d1)) { 418845530cf1Skardel if (SRCADR(d1) < SRCADR(d2)) 418945530cf1Skardel return -1; 419045530cf1Skardel else if (SRCADR(d1) == SRCADR(d2)) 419145530cf1Skardel return 0; 419245530cf1Skardel else 419345530cf1Skardel return 1; 419445530cf1Skardel } 419545530cf1Skardel 4196f40817b7Skardel for (i = 0; i < (int)sizeof(NSRCADR6(d1)); i++) { 419745530cf1Skardel if (NSRCADR6(d1)[i] < NSRCADR6(d2)[i]) 419845530cf1Skardel return -1; 419945530cf1Skardel else if (NSRCADR6(d1)[i] > NSRCADR6(d2)[i]) 420045530cf1Skardel return 1; 420145530cf1Skardel } 420245530cf1Skardel 420345530cf1Skardel return 0; 420445530cf1Skardel } 420545530cf1Skardel 420645530cf1Skardel 420745530cf1Skardel 420845530cf1Skardel /* 420945530cf1Skardel * fetch an interface structure the matches the 421045530cf1Skardel * address and has the given flags NOT set 421145530cf1Skardel */ 4212b3d6264cSchristos endpt * 421345530cf1Skardel getinterface( 421445530cf1Skardel sockaddr_u * addr, 421545530cf1Skardel u_int32 flags 421645530cf1Skardel ) 421745530cf1Skardel { 421845530cf1Skardel endpt *iface; 4219abb0f93cSkardel 4220abb0f93cSkardel iface = find_addr_in_list(addr); 4221abb0f93cSkardel 4222abb0f93cSkardel if (iface != NULL && (iface->flags & flags)) 4223abb0f93cSkardel iface = NULL; 4224abb0f93cSkardel 4225abb0f93cSkardel return iface; 4226abb0f93cSkardel } 4227abb0f93cSkardel 4228abb0f93cSkardel 4229abb0f93cSkardel /* 4230abb0f93cSkardel * findbcastinter - find broadcast interface corresponding to address 4231abb0f93cSkardel */ 423245530cf1Skardel endpt * 4233abb0f93cSkardel findbcastinter( 4234abb0f93cSkardel sockaddr_u *addr 4235abb0f93cSkardel ) 4236abb0f93cSkardel { 4237b3d6264cSchristos endpt * iface; 4238b3d6264cSchristos 4239b3d6264cSchristos iface = NULL; 4240abb0f93cSkardel #if !defined(MPE) && (defined(SIOCGIFCONF) || defined(SYS_WINNT)) 4241abb0f93cSkardel DPRINTF(4, ("Finding broadcast/multicast interface for addr %s in list of addresses\n", 4242abb0f93cSkardel stoa(addr))); 4243abb0f93cSkardel 4244abb0f93cSkardel iface = findlocalinterface(addr, INT_LOOPBACK | INT_WILDCARD, 4245abb0f93cSkardel 1); 4246abb0f93cSkardel if (iface != NULL) { 4247abb0f93cSkardel DPRINTF(4, ("Easily found bcast-/mcast- interface index #%d %s\n", 4248abb0f93cSkardel iface->ifnum, iface->name)); 4249abb0f93cSkardel return iface; 4250abb0f93cSkardel } 4251abb0f93cSkardel 4252abb0f93cSkardel /* 4253abb0f93cSkardel * plan B - try to find something reasonable in our lists in 4254abb0f93cSkardel * case kernel lookup doesn't help 4255abb0f93cSkardel */ 425645530cf1Skardel for (iface = ep_list; iface != NULL; iface = iface->elink) { 4257abb0f93cSkardel if (iface->flags & INT_WILDCARD) 4258abb0f93cSkardel continue; 4259abb0f93cSkardel 4260abb0f93cSkardel /* Don't bother with ignored interfaces */ 4261abb0f93cSkardel if (iface->ignore_packets) 4262abb0f93cSkardel continue; 4263abb0f93cSkardel 4264abb0f93cSkardel /* 4265abb0f93cSkardel * First look if this is the correct family 4266abb0f93cSkardel */ 4267abb0f93cSkardel if(AF(&iface->sin) != AF(addr)) 4268abb0f93cSkardel continue; 4269abb0f93cSkardel 4270abb0f93cSkardel /* Skip the loopback addresses */ 4271abb0f93cSkardel if (iface->flags & INT_LOOPBACK) 4272abb0f93cSkardel continue; 4273abb0f93cSkardel 4274abb0f93cSkardel /* 4275abb0f93cSkardel * If we are looking to match a multicast address and 4276abb0f93cSkardel * this interface is one... 4277abb0f93cSkardel */ 4278abb0f93cSkardel if (addr_ismulticast(addr) 4279abb0f93cSkardel && (iface->flags & INT_MULTICAST)) { 4280abb0f93cSkardel #ifdef INCLUDE_IPV6_SUPPORT 4281abb0f93cSkardel /* 4282abb0f93cSkardel * ...it is the winner unless we're looking for 4283abb0f93cSkardel * an interface to use for link-local multicast 4284abb0f93cSkardel * and its address is not link-local. 4285abb0f93cSkardel */ 4286abb0f93cSkardel if (IS_IPV6(addr) 4287abb0f93cSkardel && IN6_IS_ADDR_MC_LINKLOCAL(PSOCK_ADDR6(addr)) 4288abb0f93cSkardel && !IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(&iface->sin))) 4289abb0f93cSkardel continue; 4290abb0f93cSkardel #endif 4291abb0f93cSkardel break; 4292abb0f93cSkardel } 4293abb0f93cSkardel 4294abb0f93cSkardel /* 4295abb0f93cSkardel * We match only those interfaces marked as 4296abb0f93cSkardel * broadcastable and either the explicit broadcast 4297abb0f93cSkardel * address or the network portion of the IP address. 4298abb0f93cSkardel * Sloppy. 4299abb0f93cSkardel */ 4300abb0f93cSkardel if (IS_IPV4(addr)) { 4301abb0f93cSkardel if (SOCK_EQ(&iface->bcast, addr)) 4302abb0f93cSkardel break; 4303abb0f93cSkardel 4304abb0f93cSkardel if ((NSRCADR(&iface->sin) & NSRCADR(&iface->mask)) 4305abb0f93cSkardel == (NSRCADR(addr) & NSRCADR(&iface->mask))) 4306abb0f93cSkardel break; 4307abb0f93cSkardel } 4308abb0f93cSkardel #ifdef INCLUDE_IPV6_SUPPORT 4309abb0f93cSkardel else if (IS_IPV6(addr)) { 4310abb0f93cSkardel if (SOCK_EQ(&iface->bcast, addr)) 4311abb0f93cSkardel break; 4312abb0f93cSkardel 4313abb0f93cSkardel if (SOCK_EQ(netof(&iface->sin), netof(addr))) 4314abb0f93cSkardel break; 4315abb0f93cSkardel } 4316abb0f93cSkardel #endif 4317abb0f93cSkardel } 4318abb0f93cSkardel #endif /* SIOCGIFCONF */ 4319abb0f93cSkardel if (NULL == iface) { 4320abb0f93cSkardel DPRINTF(4, ("No bcast interface found for %s\n", 4321abb0f93cSkardel stoa(addr))); 4322abb0f93cSkardel iface = ANY_INTERFACE_CHOOSE(addr); 4323b3d6264cSchristos } else { 4324abb0f93cSkardel DPRINTF(4, ("Found bcast-/mcast- interface index #%d %s\n", 4325abb0f93cSkardel iface->ifnum, iface->name)); 4326b3d6264cSchristos } 4327b3d6264cSchristos 4328abb0f93cSkardel return iface; 4329abb0f93cSkardel } 4330abb0f93cSkardel 4331abb0f93cSkardel 4332abb0f93cSkardel /* 4333abb0f93cSkardel * io_clr_stats - clear I/O module statistics 4334abb0f93cSkardel */ 4335abb0f93cSkardel void 4336abb0f93cSkardel io_clr_stats(void) 4337abb0f93cSkardel { 4338abb0f93cSkardel packets_dropped = 0; 4339abb0f93cSkardel packets_ignored = 0; 4340abb0f93cSkardel packets_received = 0; 4341abb0f93cSkardel packets_sent = 0; 4342abb0f93cSkardel packets_notsent = 0; 4343abb0f93cSkardel 4344abb0f93cSkardel handler_calls = 0; 4345abb0f93cSkardel handler_pkts = 0; 4346abb0f93cSkardel io_timereset = current_time; 4347abb0f93cSkardel } 4348abb0f93cSkardel 4349abb0f93cSkardel 4350abb0f93cSkardel #ifdef REFCLOCK 4351abb0f93cSkardel /* 4352abb0f93cSkardel * io_addclock - add a reference clock to the list and arrange that we 4353abb0f93cSkardel * get SIGIO interrupts from it. 4354abb0f93cSkardel */ 4355abb0f93cSkardel int 4356abb0f93cSkardel io_addclock( 4357abb0f93cSkardel struct refclockio *rio 4358abb0f93cSkardel ) 4359abb0f93cSkardel { 4360abb0f93cSkardel BLOCKIO(); 4361abb0f93cSkardel 4362abb0f93cSkardel /* 4363abb0f93cSkardel * Stuff the I/O structure in the list and mark the descriptor 4364abb0f93cSkardel * in use. There is a harmless (I hope) race condition here. 4365abb0f93cSkardel */ 4366b3d6264cSchristos rio->active = TRUE; 4367abb0f93cSkardel 4368abb0f93cSkardel # ifdef HAVE_SIGNALED_IO 4369abb0f93cSkardel if (init_clock_sig(rio)) { 4370abb0f93cSkardel UNBLOCKIO(); 4371abb0f93cSkardel return 0; 4372abb0f93cSkardel } 4373abb0f93cSkardel # elif defined(HAVE_IO_COMPLETION_PORT) 4374335f7552Schristos if (!io_completion_port_add_clock_io(rio)) { 4375abb0f93cSkardel UNBLOCKIO(); 4376abb0f93cSkardel return 0; 4377abb0f93cSkardel } 4378abb0f93cSkardel # endif 4379abb0f93cSkardel 4380abb0f93cSkardel /* 4381abb0f93cSkardel * enqueue 4382abb0f93cSkardel */ 4383b3d6264cSchristos LINK_SLIST(refio, rio, next); 4384abb0f93cSkardel 4385abb0f93cSkardel /* 4386abb0f93cSkardel * register fd 4387abb0f93cSkardel */ 4388abb0f93cSkardel add_fd_to_list(rio->fd, FD_TYPE_FILE); 4389abb0f93cSkardel 4390abb0f93cSkardel UNBLOCKIO(); 4391abb0f93cSkardel return 1; 4392abb0f93cSkardel } 4393abb0f93cSkardel 4394b3d6264cSchristos 4395abb0f93cSkardel /* 4396abb0f93cSkardel * io_closeclock - close the clock in the I/O structure given 4397abb0f93cSkardel */ 4398abb0f93cSkardel void 4399abb0f93cSkardel io_closeclock( 4400abb0f93cSkardel struct refclockio *rio 4401abb0f93cSkardel ) 4402abb0f93cSkardel { 4403b3d6264cSchristos struct refclockio *unlinked; 4404abb0f93cSkardel 4405abb0f93cSkardel BLOCKIO(); 4406abb0f93cSkardel 4407abb0f93cSkardel /* 4408abb0f93cSkardel * Remove structure from the list 4409abb0f93cSkardel */ 4410b3d6264cSchristos rio->active = FALSE; 4411b3d6264cSchristos UNLINK_SLIST(unlinked, refio, rio, next, struct refclockio); 4412b3d6264cSchristos if (NULL != unlinked) { 4413335f7552Schristos /* Close the descriptor. The order of operations is 4414335f7552Schristos * important here in case of async / overlapped IO: 4415335f7552Schristos * only after we have removed the clock from the 4416335f7552Schristos * IO completion port we can be sure no further 4417335f7552Schristos * input is queued. So... 4418335f7552Schristos * - we first disable feeding to the queu by removing 4419335f7552Schristos * the clock from the IO engine 4420335f7552Schristos * - close the file (which brings down any IO on it) 4421335f7552Schristos * - clear the buffer from results for this fd 4422abb0f93cSkardel */ 4423335f7552Schristos # ifdef HAVE_IO_COMPLETION_PORT 4424335f7552Schristos io_completion_port_remove_clock_io(rio); 4425335f7552Schristos # endif 4426abb0f93cSkardel close_and_delete_fd_from_list(rio->fd); 4427335f7552Schristos purge_recv_buffers_for_fd(rio->fd); 4428b3d6264cSchristos rio->fd = -1; 4429335f7552Schristos } 4430b3d6264cSchristos 4431abb0f93cSkardel UNBLOCKIO(); 4432abb0f93cSkardel } 4433abb0f93cSkardel #endif /* REFCLOCK */ 4434abb0f93cSkardel 4435b3d6264cSchristos 4436abb0f93cSkardel /* 4437abb0f93cSkardel * On NT a SOCKET is an unsigned int so we cannot possibly keep it in 4438abb0f93cSkardel * an array. So we use one of the ISC_LIST functions to hold the 4439abb0f93cSkardel * socket value and use that when we want to enumerate it. 4440abb0f93cSkardel * 4441abb0f93cSkardel * This routine is called by the forked intres child process to close 4442abb0f93cSkardel * all open sockets. On Windows there's no need as intres runs in 4443abb0f93cSkardel * the same process as a thread. 4444abb0f93cSkardel */ 4445abb0f93cSkardel #ifndef SYS_WINNT 4446abb0f93cSkardel void 4447b3d6264cSchristos kill_asyncio( 4448b3d6264cSchristos int startfd 4449b3d6264cSchristos ) 4450abb0f93cSkardel { 4451abb0f93cSkardel BLOCKIO(); 4452abb0f93cSkardel 4453abb0f93cSkardel /* 4454abb0f93cSkardel * In the child process we do not maintain activefds and 4455abb0f93cSkardel * maxactivefd. Zeroing maxactivefd disables code which 4456abb0f93cSkardel * maintains it in close_and_delete_fd_from_list(). 4457abb0f93cSkardel */ 4458abb0f93cSkardel maxactivefd = 0; 4459abb0f93cSkardel 4460abb0f93cSkardel while (fd_list != NULL) 4461abb0f93cSkardel close_and_delete_fd_from_list(fd_list->fd); 4462abb0f93cSkardel 4463abb0f93cSkardel UNBLOCKIO(); 4464abb0f93cSkardel } 4465abb0f93cSkardel #endif /* !SYS_WINNT */ 4466abb0f93cSkardel 4467b3d6264cSchristos 4468abb0f93cSkardel /* 4469abb0f93cSkardel * Add and delete functions for the list of open sockets 4470abb0f93cSkardel */ 4471abb0f93cSkardel static void 4472abb0f93cSkardel add_fd_to_list( 4473abb0f93cSkardel SOCKET fd, 4474abb0f93cSkardel enum desc_type type 4475abb0f93cSkardel ) 4476abb0f93cSkardel { 4477abb0f93cSkardel vsock_t *lsock = emalloc(sizeof(*lsock)); 4478abb0f93cSkardel 4479abb0f93cSkardel lsock->fd = fd; 4480abb0f93cSkardel lsock->type = type; 4481abb0f93cSkardel 4482abb0f93cSkardel LINK_SLIST(fd_list, lsock, link); 4483b3d6264cSchristos maintain_activefds(fd, 0); 4484abb0f93cSkardel } 4485abb0f93cSkardel 4486abb0f93cSkardel 4487abb0f93cSkardel static void 4488abb0f93cSkardel close_and_delete_fd_from_list( 4489abb0f93cSkardel SOCKET fd 4490abb0f93cSkardel ) 4491abb0f93cSkardel { 4492abb0f93cSkardel vsock_t *lsock; 4493abb0f93cSkardel 4494abb0f93cSkardel UNLINK_EXPR_SLIST(lsock, fd_list, fd == 4495abb0f93cSkardel UNLINK_EXPR_SLIST_CURRENT()->fd, link, vsock_t); 4496abb0f93cSkardel 4497b3d6264cSchristos if (NULL == lsock) 4498b3d6264cSchristos return; 4499b3d6264cSchristos 4500abb0f93cSkardel switch (lsock->type) { 4501b3d6264cSchristos 4502abb0f93cSkardel case FD_TYPE_SOCKET: 4503abb0f93cSkardel closesocket(lsock->fd); 4504abb0f93cSkardel break; 4505abb0f93cSkardel 4506abb0f93cSkardel case FD_TYPE_FILE: 4507bd25f4c4Schristos closeserial((int)lsock->fd); 4508abb0f93cSkardel break; 4509abb0f93cSkardel 4510abb0f93cSkardel default: 4511abb0f93cSkardel msyslog(LOG_ERR, 4512abb0f93cSkardel "internal error - illegal descriptor type %d - EXITING", 4513abb0f93cSkardel (int)lsock->type); 4514abb0f93cSkardel exit(1); 4515abb0f93cSkardel } 4516abb0f93cSkardel 4517abb0f93cSkardel free(lsock); 4518abb0f93cSkardel /* 4519abb0f93cSkardel * remove from activefds 4520abb0f93cSkardel */ 4521b3d6264cSchristos maintain_activefds(fd, 1); 4522b3d6264cSchristos } 4523abb0f93cSkardel 4524abb0f93cSkardel 4525abb0f93cSkardel static void 4526abb0f93cSkardel add_addr_to_list( 4527abb0f93cSkardel sockaddr_u * addr, 452845530cf1Skardel endpt * ep 4529abb0f93cSkardel ) 4530abb0f93cSkardel { 4531abb0f93cSkardel remaddr_t *laddr; 4532abb0f93cSkardel 4533abb0f93cSkardel #ifdef DEBUG 4534abb0f93cSkardel if (find_addr_in_list(addr) == NULL) { 4535abb0f93cSkardel #endif 4536abb0f93cSkardel /* not there yet - add to list */ 4537abb0f93cSkardel laddr = emalloc(sizeof(*laddr)); 453845530cf1Skardel laddr->addr = *addr; 453945530cf1Skardel laddr->ep = ep; 4540abb0f93cSkardel 4541abb0f93cSkardel LINK_SLIST(remoteaddr_list, laddr, link); 4542abb0f93cSkardel 4543abb0f93cSkardel DPRINTF(4, ("Added addr %s to list of addresses\n", 4544abb0f93cSkardel stoa(addr))); 4545abb0f93cSkardel #ifdef DEBUG 4546abb0f93cSkardel } else 4547abb0f93cSkardel DPRINTF(4, ("WARNING: Attempt to add duplicate addr %s to address list\n", 4548abb0f93cSkardel stoa(addr))); 4549abb0f93cSkardel #endif 4550abb0f93cSkardel } 4551abb0f93cSkardel 4552abb0f93cSkardel 4553abb0f93cSkardel static void 4554abb0f93cSkardel delete_addr_from_list( 4555abb0f93cSkardel sockaddr_u *addr 4556abb0f93cSkardel ) 4557abb0f93cSkardel { 4558abb0f93cSkardel remaddr_t *unlinked; 4559abb0f93cSkardel 4560abb0f93cSkardel UNLINK_EXPR_SLIST(unlinked, remoteaddr_list, SOCK_EQ(addr, 4561abb0f93cSkardel &(UNLINK_EXPR_SLIST_CURRENT()->addr)), link, remaddr_t); 4562abb0f93cSkardel 4563abb0f93cSkardel if (unlinked != NULL) { 4564abb0f93cSkardel DPRINTF(4, ("Deleted addr %s from list of addresses\n", 4565abb0f93cSkardel stoa(addr))); 4566abb0f93cSkardel free(unlinked); 4567abb0f93cSkardel } 4568abb0f93cSkardel } 4569abb0f93cSkardel 4570abb0f93cSkardel 4571abb0f93cSkardel static void 4572abb0f93cSkardel delete_interface_from_list( 457345530cf1Skardel endpt *iface 4574abb0f93cSkardel ) 4575abb0f93cSkardel { 4576abb0f93cSkardel remaddr_t *unlinked; 4577abb0f93cSkardel 4578ad131110Schristos for (;;) { 4579abb0f93cSkardel UNLINK_EXPR_SLIST(unlinked, remoteaddr_list, iface == 458045530cf1Skardel UNLINK_EXPR_SLIST_CURRENT()->ep, link, 4581abb0f93cSkardel remaddr_t); 4582abb0f93cSkardel 4583ad131110Schristos if (unlinked == NULL) 4584ad131110Schristos break; 4585abb0f93cSkardel DPRINTF(4, ("Deleted addr %s for interface #%d %s from list of addresses\n", 4586abb0f93cSkardel stoa(&unlinked->addr), iface->ifnum, 4587abb0f93cSkardel iface->name)); 4588abb0f93cSkardel free(unlinked); 4589abb0f93cSkardel } 4590abb0f93cSkardel } 4591abb0f93cSkardel 4592abb0f93cSkardel 4593abb0f93cSkardel static struct interface * 4594abb0f93cSkardel find_addr_in_list( 4595abb0f93cSkardel sockaddr_u *addr 4596abb0f93cSkardel ) 4597abb0f93cSkardel { 4598abb0f93cSkardel remaddr_t *entry; 4599abb0f93cSkardel 4600abb0f93cSkardel DPRINTF(4, ("Searching for addr %s in list of addresses - ", 4601abb0f93cSkardel stoa(addr))); 4602abb0f93cSkardel 4603abb0f93cSkardel for (entry = remoteaddr_list; 4604abb0f93cSkardel entry != NULL; 4605abb0f93cSkardel entry = entry->link) 4606abb0f93cSkardel if (SOCK_EQ(&entry->addr, addr)) { 4607abb0f93cSkardel DPRINTF(4, ("FOUND\n")); 460845530cf1Skardel return entry->ep; 4609abb0f93cSkardel } 4610abb0f93cSkardel 4611abb0f93cSkardel DPRINTF(4, ("NOT FOUND\n")); 4612abb0f93cSkardel return NULL; 4613abb0f93cSkardel } 4614abb0f93cSkardel 4615abb0f93cSkardel 4616abb0f93cSkardel /* 4617abb0f93cSkardel * Find the given address with the all given flags set in the list 4618abb0f93cSkardel */ 461945530cf1Skardel static endpt * 4620abb0f93cSkardel find_flagged_addr_in_list( 4621abb0f93cSkardel sockaddr_u * addr, 462245530cf1Skardel u_int32 flags 4623abb0f93cSkardel ) 4624abb0f93cSkardel { 4625abb0f93cSkardel remaddr_t *entry; 4626abb0f93cSkardel 4627abb0f93cSkardel DPRINTF(4, ("Finding addr %s with flags %d in list: ", 4628abb0f93cSkardel stoa(addr), flags)); 4629abb0f93cSkardel 4630abb0f93cSkardel for (entry = remoteaddr_list; 4631abb0f93cSkardel entry != NULL; 4632abb0f93cSkardel entry = entry->link) 4633abb0f93cSkardel 4634abb0f93cSkardel if (SOCK_EQ(&entry->addr, addr) 463545530cf1Skardel && (entry->ep->flags & flags) == flags) { 4636abb0f93cSkardel 4637abb0f93cSkardel DPRINTF(4, ("FOUND\n")); 463845530cf1Skardel return entry->ep; 4639abb0f93cSkardel } 4640abb0f93cSkardel 4641abb0f93cSkardel DPRINTF(4, ("NOT FOUND\n")); 4642abb0f93cSkardel return NULL; 4643abb0f93cSkardel } 4644abb0f93cSkardel 4645abb0f93cSkardel 464645530cf1Skardel const char * 464745530cf1Skardel localaddrtoa( 464845530cf1Skardel endpt *la 464945530cf1Skardel ) 465045530cf1Skardel { 465145530cf1Skardel return (NULL == la) 465245530cf1Skardel ? "<null>" 465345530cf1Skardel : stoa(&la->sin); 465445530cf1Skardel } 465545530cf1Skardel 465645530cf1Skardel 4657abb0f93cSkardel #ifdef HAS_ROUTING_SOCKET 4658abb0f93cSkardel # ifndef UPDATE_GRACE 4659abb0f93cSkardel # define UPDATE_GRACE 2 /* wait UPDATE_GRACE seconds before scanning */ 4660abb0f93cSkardel # endif 4661abb0f93cSkardel 4662abb0f93cSkardel static void 4663abb0f93cSkardel process_routing_msgs(struct asyncio_reader *reader) 4664abb0f93cSkardel { 4665abb0f93cSkardel char buffer[5120]; 4666abb0f93cSkardel int cnt, msg_type; 4667abb0f93cSkardel #ifdef HAVE_RTNETLINK 4668abb0f93cSkardel struct nlmsghdr *nh; 4669abb0f93cSkardel #else 4670b3d6264cSchristos struct rt_msghdr rtm; 4671abb0f93cSkardel char *p; 4672abb0f93cSkardel #endif 4673abb0f93cSkardel 4674abb0f93cSkardel if (disable_dynamic_updates) { 4675abb0f93cSkardel /* 4676abb0f93cSkardel * discard ourselves if we are not needed any more 4677abb0f93cSkardel * usually happens when running unprivileged 4678abb0f93cSkardel */ 4679abb0f93cSkardel remove_asyncio_reader(reader); 4680abb0f93cSkardel delete_asyncio_reader(reader); 4681abb0f93cSkardel return; 4682abb0f93cSkardel } 4683abb0f93cSkardel 4684abb0f93cSkardel cnt = read(reader->fd, buffer, sizeof(buffer)); 4685abb0f93cSkardel 4686abb0f93cSkardel if (cnt < 0) { 468709f14f80Schristos if (errno == ENOBUFS) { 4688abb0f93cSkardel msyslog(LOG_ERR, 468909f14f80Schristos "routing socket reports: %m"); 469009f14f80Schristos } else { 469109f14f80Schristos msyslog(LOG_ERR, 469209f14f80Schristos "routing socket reports: %m - disabling"); 4693abb0f93cSkardel remove_asyncio_reader(reader); 4694abb0f93cSkardel delete_asyncio_reader(reader); 469509f14f80Schristos } 4696abb0f93cSkardel return; 4697abb0f93cSkardel } 4698abb0f93cSkardel 4699abb0f93cSkardel /* 4700abb0f93cSkardel * process routing message 4701abb0f93cSkardel */ 4702abb0f93cSkardel #ifdef HAVE_RTNETLINK 4703bd25f4c4Schristos for (nh = UA_PTR(struct nlmsghdr, buffer); 4704abb0f93cSkardel NLMSG_OK(nh, cnt); 4705abb0f93cSkardel nh = NLMSG_NEXT(nh, cnt)) { 4706abb0f93cSkardel msg_type = nh->nlmsg_type; 4707abb0f93cSkardel #else 4708abb0f93cSkardel for (p = buffer; 4709abb0f93cSkardel (p + sizeof(struct rt_msghdr)) <= (buffer + cnt); 4710b3d6264cSchristos p += rtm.rtm_msglen) { 4711b3d6264cSchristos memcpy(&rtm, p, sizeof(rtm)); 4712b3d6264cSchristos if (rtm.rtm_version != RTM_VERSION) { 4713abb0f93cSkardel msyslog(LOG_ERR, 4714abb0f93cSkardel "version mismatch (got %d - expected %d) on routing socket - disabling", 4715b3d6264cSchristos rtm.rtm_version, RTM_VERSION); 4716abb0f93cSkardel 4717abb0f93cSkardel remove_asyncio_reader(reader); 4718abb0f93cSkardel delete_asyncio_reader(reader); 4719abb0f93cSkardel return; 4720abb0f93cSkardel } 4721b3d6264cSchristos msg_type = rtm.rtm_type; 4722abb0f93cSkardel #endif 4723abb0f93cSkardel switch (msg_type) { 4724abb0f93cSkardel #ifdef RTM_NEWADDR 4725abb0f93cSkardel case RTM_NEWADDR: 4726abb0f93cSkardel #endif 4727abb0f93cSkardel #ifdef RTM_DELADDR 4728abb0f93cSkardel case RTM_DELADDR: 4729abb0f93cSkardel #endif 4730abb0f93cSkardel #ifdef RTM_ADD 4731abb0f93cSkardel case RTM_ADD: 4732abb0f93cSkardel #endif 4733abb0f93cSkardel #ifdef RTM_DELETE 4734abb0f93cSkardel case RTM_DELETE: 4735abb0f93cSkardel #endif 4736abb0f93cSkardel #ifdef RTM_REDIRECT 4737abb0f93cSkardel case RTM_REDIRECT: 4738abb0f93cSkardel #endif 4739abb0f93cSkardel #ifdef RTM_CHANGE 4740abb0f93cSkardel case RTM_CHANGE: 4741abb0f93cSkardel #endif 4742abb0f93cSkardel #ifdef RTM_LOSING 4743abb0f93cSkardel case RTM_LOSING: 4744abb0f93cSkardel #endif 4745abb0f93cSkardel #ifdef RTM_IFINFO 4746abb0f93cSkardel case RTM_IFINFO: 4747abb0f93cSkardel #endif 4748abb0f93cSkardel #ifdef RTM_IFANNOUNCE 4749abb0f93cSkardel case RTM_IFANNOUNCE: 4750abb0f93cSkardel #endif 4751abb0f93cSkardel #ifdef RTM_NEWLINK 4752abb0f93cSkardel case RTM_NEWLINK: 4753abb0f93cSkardel #endif 4754abb0f93cSkardel #ifdef RTM_DELLINK 4755abb0f93cSkardel case RTM_DELLINK: 4756abb0f93cSkardel #endif 4757abb0f93cSkardel #ifdef RTM_NEWROUTE 4758abb0f93cSkardel case RTM_NEWROUTE: 4759abb0f93cSkardel #endif 4760abb0f93cSkardel #ifdef RTM_DELROUTE 4761abb0f93cSkardel case RTM_DELROUTE: 4762abb0f93cSkardel #endif 4763abb0f93cSkardel /* 4764abb0f93cSkardel * we are keen on new and deleted addresses and 4765abb0f93cSkardel * if an interface goes up and down or routing 4766abb0f93cSkardel * changes 4767abb0f93cSkardel */ 4768abb0f93cSkardel DPRINTF(3, ("routing message op = %d: scheduling interface update\n", 4769abb0f93cSkardel msg_type)); 4770abb0f93cSkardel timer_interfacetimeout(current_time + UPDATE_GRACE); 4771abb0f93cSkardel break; 4772abb0f93cSkardel #ifdef HAVE_RTNETLINK 4773abb0f93cSkardel case NLMSG_DONE: 4774abb0f93cSkardel /* end of multipart message */ 4775abb0f93cSkardel return; 4776abb0f93cSkardel #endif 4777abb0f93cSkardel default: 4778abb0f93cSkardel /* 4779abb0f93cSkardel * the rest doesn't bother us. 4780abb0f93cSkardel */ 4781abb0f93cSkardel DPRINTF(4, ("routing message op = %d: ignored\n", 4782abb0f93cSkardel msg_type)); 4783abb0f93cSkardel break; 4784abb0f93cSkardel } 4785abb0f93cSkardel } 4786abb0f93cSkardel } 4787abb0f93cSkardel 4788abb0f93cSkardel /* 4789abb0f93cSkardel * set up routing notifications 4790abb0f93cSkardel */ 4791abb0f93cSkardel static void 4792abb0f93cSkardel init_async_notifications() 4793abb0f93cSkardel { 4794abb0f93cSkardel struct asyncio_reader *reader; 4795abb0f93cSkardel #ifdef HAVE_RTNETLINK 4796abb0f93cSkardel int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 4797abb0f93cSkardel struct sockaddr_nl sa; 4798abb0f93cSkardel #else 4799abb0f93cSkardel int fd = socket(PF_ROUTE, SOCK_RAW, 0); 4800abb0f93cSkardel #endif 4801867deecaSroy #ifdef RO_MSGFILTER 4802867deecaSroy unsigned char msgfilter[] = { 4803867deecaSroy #ifdef RTM_NEWADDR 4804867deecaSroy RTM_NEWADDR, 4805867deecaSroy #endif 4806867deecaSroy #ifdef RTM_DELADDR 4807867deecaSroy RTM_DELADDR, 4808867deecaSroy #endif 4809867deecaSroy #ifdef RTM_ADD 4810867deecaSroy RTM_ADD, 4811867deecaSroy #endif 4812867deecaSroy #ifdef RTM_DELETE 4813867deecaSroy RTM_DELETE, 4814867deecaSroy #endif 4815867deecaSroy #ifdef RTM_REDIRECT 4816867deecaSroy RTM_REDIRECT, 4817867deecaSroy #endif 4818867deecaSroy #ifdef RTM_CHANGE 4819867deecaSroy RTM_CHANGE, 4820867deecaSroy #endif 4821867deecaSroy #ifdef RTM_LOSING 4822867deecaSroy RTM_LOSING, 4823867deecaSroy #endif 4824867deecaSroy #ifdef RTM_IFINFO 4825867deecaSroy RTM_IFINFO, 4826867deecaSroy #endif 4827867deecaSroy #ifdef RTM_IFANNOUNCE 4828867deecaSroy RTM_IFANNOUNCE, 4829867deecaSroy #endif 4830867deecaSroy #ifdef RTM_NEWLINK 4831867deecaSroy RTM_NEWLINK, 4832867deecaSroy #endif 4833867deecaSroy #ifdef RTM_DELLINK 4834867deecaSroy RTM_DELLINK, 4835867deecaSroy #endif 4836867deecaSroy #ifdef RTM_NEWROUTE 4837867deecaSroy RTM_NEWROUTE, 4838867deecaSroy #endif 4839867deecaSroy #ifdef RTM_DELROUTE 4840867deecaSroy RTM_DELROUTE, 4841867deecaSroy #endif 4842867deecaSroy }; 4843867deecaSroy #endif /* !RO_MSGFILTER */ 4844867deecaSroy 4845abb0f93cSkardel if (fd < 0) { 4846abb0f93cSkardel msyslog(LOG_ERR, 4847abb0f93cSkardel "unable to open routing socket (%m) - using polled interface update"); 4848abb0f93cSkardel return; 4849abb0f93cSkardel } 4850abb0f93cSkardel 4851abb0f93cSkardel fd = move_fd(fd); 4852abb0f93cSkardel #ifdef HAVE_RTNETLINK 4853b3d6264cSchristos ZERO(sa); 4854abb0f93cSkardel sa.nl_family = PF_NETLINK; 4855abb0f93cSkardel sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR 4856abb0f93cSkardel | RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_ROUTE 4857abb0f93cSkardel | RTMGRP_IPV4_MROUTE | RTMGRP_IPV6_ROUTE 4858abb0f93cSkardel | RTMGRP_IPV6_MROUTE; 4859abb0f93cSkardel if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 4860abb0f93cSkardel msyslog(LOG_ERR, 4861abb0f93cSkardel "bind failed on routing socket (%m) - using polled interface update"); 4862abb0f93cSkardel return; 4863abb0f93cSkardel } 4864abb0f93cSkardel #endif 4865867deecaSroy #ifdef RO_MSGFILTER 4866867deecaSroy if (setsockopt(fd, PF_ROUTE, RO_MSGFILTER, 4867867deecaSroy &msgfilter, sizeof(msgfilter)) == -1) 4868867deecaSroy msyslog(LOG_ERR, "RO_MSGFILTER: %m"); 4869867deecaSroy #endif 4870b3d6264cSchristos make_socket_nonblocking(fd); 4871abb0f93cSkardel #if defined(HAVE_SIGNALED_IO) 4872abb0f93cSkardel init_socket_sig(fd); 4873abb0f93cSkardel #endif /* HAVE_SIGNALED_IO */ 4874abb0f93cSkardel 4875abb0f93cSkardel reader = new_asyncio_reader(); 4876abb0f93cSkardel 4877abb0f93cSkardel reader->fd = fd; 4878abb0f93cSkardel reader->receiver = process_routing_msgs; 4879abb0f93cSkardel 4880abb0f93cSkardel add_asyncio_reader(reader, FD_TYPE_SOCKET); 4881abb0f93cSkardel msyslog(LOG_INFO, 4882abb0f93cSkardel "Listening on routing socket on fd #%d for interface updates", 4883abb0f93cSkardel fd); 4884abb0f93cSkardel } 4885abb0f93cSkardel #else 4886abb0f93cSkardel /* HAS_ROUTING_SOCKET not defined */ 4887abb0f93cSkardel static void 4888abb0f93cSkardel init_async_notifications(void) 4889abb0f93cSkardel { 4890abb0f93cSkardel } 4891abb0f93cSkardel #endif 4892b3d6264cSchristos 4893