154359Sroberto/* 254359Sroberto * ntp_io.c - input/output routines for ntpd. The socket-opening code 354359Sroberto * was shamelessly stolen from ntpd. 454359Sroberto */ 554359Sroberto 654359Sroberto#ifdef HAVE_CONFIG_H 754359Sroberto# include <config.h> 854359Sroberto#endif 954359Sroberto 10285612Sdelphij#include <stdio.h> 11285612Sdelphij#include <signal.h> 12285612Sdelphij#ifdef HAVE_FNMATCH_H 13285612Sdelphij# include <fnmatch.h> 14285612Sdelphij# if !defined(FNM_CASEFOLD) && defined(FNM_IGNORECASE) 15285612Sdelphij# define FNM_CASEFOLD FNM_IGNORECASE 16285612Sdelphij# endif 17285612Sdelphij#endif 18285612Sdelphij#ifdef HAVE_SYS_PARAM_H 19285612Sdelphij# include <sys/param.h> 20285612Sdelphij#endif 21285612Sdelphij#ifdef HAVE_SYS_IOCTL_H 22285612Sdelphij# include <sys/ioctl.h> 23285612Sdelphij#endif 24285612Sdelphij#ifdef HAVE_SYS_SOCKIO_H /* UXPV: SIOC* #defines (Frank Vance <fvance@waii.com>) */ 25285612Sdelphij# include <sys/sockio.h> 26285612Sdelphij#endif 27285612Sdelphij#ifdef HAVE_SYS_UIO_H 28285612Sdelphij# include <sys/uio.h> 29285612Sdelphij#endif 30285612Sdelphij 3182498Sroberto#include "ntp_machine.h" 3282498Sroberto#include "ntpd.h" 3382498Sroberto#include "ntp_io.h" 3482498Sroberto#include "iosignal.h" 35285612Sdelphij#include "ntp_lists.h" 3682498Sroberto#include "ntp_refclock.h" 3782498Sroberto#include "ntp_stdlib.h" 38285612Sdelphij#include "ntp_worker.h" 39182007Sroberto#include "ntp_request.h" 40285612Sdelphij#include "ntp_assert.h" 41285612Sdelphij#include "timevalops.h" 42285612Sdelphij#include "timespecops.h" 43285612Sdelphij#include "ntpd-opts.h" 44293650Sglebius#include "safecast.h" 4582498Sroberto 46132451Sroberto/* Don't include ISC's version of IPv6 variables and structures */ 47132451Sroberto#define ISC_IPV6_H 1 48285612Sdelphij#include <isc/mem.h> 49132451Sroberto#include <isc/interfaceiter.h> 50285612Sdelphij#include <isc/netaddr.h> 51132451Sroberto#include <isc/result.h> 52285612Sdelphij#include <isc/sockaddr.h> 53132451Sroberto 54132451Sroberto#ifdef SIM 55132451Sroberto#include "ntpsim.h" 56132451Sroberto#endif 57132451Sroberto 58285612Sdelphij#ifdef HAS_ROUTING_SOCKET 59285612Sdelphij# include <net/route.h> 60285612Sdelphij# ifdef HAVE_RTNETLINK 61285612Sdelphij# include <linux/rtnetlink.h> 62285612Sdelphij# endif 6354359Sroberto#endif 6454359Sroberto 65182007Sroberto/* 66182007Sroberto * setsockopt does not always have the same arg declaration 67182007Sroberto * across all platforms. If it's not defined we make it empty 68182007Sroberto */ 69182007Sroberto 70182007Sroberto#ifndef SETSOCKOPT_ARG_CAST 71182007Sroberto#define SETSOCKOPT_ARG_CAST 72182007Sroberto#endif 73182007Sroberto 74285612Sdelphijextern int listen_to_virtual_ips; 75182007Sroberto 76285612Sdelphij#ifndef IPTOS_DSCP_EF 77285612Sdelphij#define IPTOS_DSCP_EF 0xb8 78285612Sdelphij#endif 79285612Sdelphijint qos = IPTOS_DSCP_EF; /* QoS RFC3246 */ 80182007Sroberto 81285612Sdelphij#ifdef LEAP_SMEAR 82285612Sdelphij/* TODO burnicki: This should be moved to ntp_timer.c, but if we do so 83285612Sdelphij * we get a linker error. Since we're running out of time before the leap 84285612Sdelphij * second occurs, we let it here where it just works. 85285612Sdelphij */ 86285612Sdelphijint leap_smear_intv; 87285612Sdelphij#endif 88182007Sroberto 89285612Sdelphij/* 90285612Sdelphij * NIC rule entry 91285612Sdelphij */ 92285612Sdelphijtypedef struct nic_rule_tag nic_rule; 93182007Sroberto 94285612Sdelphijstruct nic_rule_tag { 95285612Sdelphij nic_rule * next; 96285612Sdelphij nic_rule_action action; 97285612Sdelphij nic_rule_match match_type; 98285612Sdelphij char * if_name; 99285612Sdelphij sockaddr_u addr; 100285612Sdelphij int prefixlen; 101285612Sdelphij}; 102182007Sroberto 103285612Sdelphij/* 104285612Sdelphij * NIC rule listhead. Entries are added at the head so that the first 105285612Sdelphij * match in the list is the last matching rule specified. 106285612Sdelphij */ 107285612Sdelphijnic_rule *nic_rule_list; 108199995Sume 109106163Sroberto 110285612Sdelphij#if defined(SO_BINTIME) && defined(SCM_BINTIME) && defined(CMSG_FIRSTHDR) 111285612Sdelphij# define HAVE_PACKET_TIMESTAMP 112285612Sdelphij# define HAVE_BINTIME 113285612Sdelphij# ifdef BINTIME_CTLMSGBUF_SIZE 114285612Sdelphij# define CMSG_BUFSIZE BINTIME_CTLMSGBUF_SIZE 115285612Sdelphij# else 116285612Sdelphij# define CMSG_BUFSIZE 1536 /* moderate default */ 117285612Sdelphij# endif 118285612Sdelphij#elif defined(SO_TIMESTAMPNS) && defined(SCM_TIMESTAMPNS) && defined(CMSG_FIRSTHDR) 119285612Sdelphij# define HAVE_PACKET_TIMESTAMP 120285612Sdelphij# define HAVE_TIMESTAMPNS 121285612Sdelphij# ifdef TIMESTAMPNS_CTLMSGBUF_SIZE 122285612Sdelphij# define CMSG_BUFSIZE TIMESTAMPNS_CTLMSGBUF_SIZE 123285612Sdelphij# else 124285612Sdelphij# define CMSG_BUFSIZE 1536 /* moderate default */ 125285612Sdelphij# endif 126285612Sdelphij#elif defined(SO_TIMESTAMP) && defined(SCM_TIMESTAMP) && defined(CMSG_FIRSTHDR) 127285612Sdelphij# define HAVE_PACKET_TIMESTAMP 128285612Sdelphij# define HAVE_TIMESTAMP 129285612Sdelphij# ifdef TIMESTAMP_CTLMSGBUF_SIZE 130285612Sdelphij# define CMSG_BUFSIZE TIMESTAMP_CTLMSGBUF_SIZE 131285612Sdelphij# else 132285612Sdelphij# define CMSG_BUFSIZE 1536 /* moderate default */ 133285612Sdelphij# endif 134182007Sroberto#else 135182007Sroberto/* fill in for old/other timestamp interfaces */ 136182007Sroberto#endif 137182007Sroberto 138132451Sroberto#if defined(SYS_WINNT) 139285612Sdelphij#include "win32_io.h" 140132451Sroberto#include <isc/win32os.h> 14154359Sroberto#endif 14254359Sroberto 143200576Sroberto/* 14454359Sroberto * We do asynchronous input using the SIGIO facility. A number of 14554359Sroberto * recvbuf buffers are preallocated for input. In the signal 14654359Sroberto * handler we poll to see which sockets are ready and read the 14754359Sroberto * packets from them into the recvbuf's along with a time stamp and 14854359Sroberto * an indication of the source host and the interface it was received 14954359Sroberto * through. This allows us to get as accurate receive time stamps 15054359Sroberto * as possible independent of other processing going on. 15154359Sroberto * 15254359Sroberto * We watch the number of recvbufs available to the signal handler 15354359Sroberto * and allocate more when this number drops below the low water 15454359Sroberto * mark. If the signal handler should run out of buffers in the 15554359Sroberto * interim it will drop incoming frames, the idea being that it is 15654359Sroberto * better to drop a packet than to be inaccurate. 15754359Sroberto */ 15854359Sroberto 15954359Sroberto 16054359Sroberto/* 16154359Sroberto * Other statistics of possible interest 16254359Sroberto */ 16354359Srobertovolatile u_long packets_dropped; /* total number of packets dropped on reception */ 16454359Srobertovolatile u_long packets_ignored; /* packets received on wild card interface */ 16554359Srobertovolatile u_long packets_received; /* total number of packets received */ 166285612Sdelphij u_long packets_sent; /* total number of packets sent */ 167285612Sdelphij u_long packets_notsent; /* total number of packets which couldn't be sent */ 16854359Sroberto 16954359Srobertovolatile u_long handler_calls; /* number of calls to interrupt handler */ 17054359Srobertovolatile u_long handler_pkts; /* number of pkts received by handler */ 17154359Srobertou_long io_timereset; /* time counters were reset */ 17254359Sroberto 17354359Sroberto/* 17454359Sroberto * Interface stuff 17554359Sroberto */ 176285612Sdelphijendpt * any_interface; /* wildcard ipv4 interface */ 177285612Sdelphijendpt * any6_interface; /* wildcard ipv6 interface */ 178285612Sdelphijendpt * loopback_interface; /* loopback ipv4 interface */ 179182007Sroberto 180285612Sdelphijisc_boolean_t broadcast_client_enabled; /* is broadcast client enabled */ 181285612Sdelphiju_int sys_ifnum; /* next .ifnum to assign */ 182132451Srobertoint ninterfaces; /* Total number of interfaces */ 18354359Sroberto 184285612Sdelphijint disable_dynamic_updates; /* scan interfaces once only */ 185182007Sroberto 18654359Sroberto#ifdef REFCLOCK 18754359Sroberto/* 18854359Sroberto * Refclock stuff. We keep a chain of structures with data concerning 18954359Sroberto * the guys we are doing I/O for. 19054359Sroberto */ 19154359Srobertostatic struct refclockio *refio; 19254359Sroberto#endif /* REFCLOCK */ 19354359Sroberto 19454359Sroberto/* 195285612Sdelphij * File descriptor masks etc. for call to select 196285612Sdelphij * Not needed for I/O Completion Ports or anything outside this file 197132451Sroberto */ 198285612Sdelphijstatic fd_set activefds; 199285612Sdelphijstatic int maxactivefd; 200132451Sroberto 201132451Sroberto/* 202182007Sroberto * bit alternating value to detect verified interfaces during an update cycle 203182007Sroberto */ 204285612Sdelphijstatic u_short sys_interphase = 0; 20554359Sroberto 206285612Sdelphijstatic endpt * new_interface(endpt *); 207285612Sdelphijstatic void add_interface(endpt *); 208285612Sdelphijstatic int update_interfaces(u_short, interface_receiver_t, 209285612Sdelphij void *); 210285612Sdelphijstatic void remove_interface(endpt *); 211285612Sdelphijstatic endpt * create_interface(u_short, endpt *); 212182007Sroberto 213285612Sdelphijstatic int is_wildcard_addr (const sockaddr_u *); 214182007Sroberto 215182007Sroberto/* 216182007Sroberto * Multicast functions 217182007Sroberto */ 218285612Sdelphijstatic isc_boolean_t addr_ismulticast (sockaddr_u *); 219289997Sglebiusstatic isc_boolean_t is_anycast (sockaddr_u *, 220285612Sdelphij const char *); 221285612Sdelphij 222182007Sroberto/* 223182007Sroberto * Not all platforms support multicast 224182007Sroberto */ 225182007Sroberto#ifdef MCAST 226285612Sdelphijstatic isc_boolean_t socket_multicast_enable (endpt *, sockaddr_u *); 227285612Sdelphijstatic isc_boolean_t socket_multicast_disable(endpt *, sockaddr_u *); 228132451Sroberto#endif 22954359Sroberto 230182007Sroberto#ifdef DEBUG 231285612Sdelphijstatic void interface_dump (const endpt *); 232285612Sdelphijstatic void sockaddr_dump (const sockaddr_u *); 233285612Sdelphijstatic void print_interface (const endpt *, const char *, const char *); 234285612Sdelphij#define DPRINT_INTERFACE(level, args) do { if (debug >= (level)) { print_interface args; } } while (0) 235182007Sroberto#else 236285612Sdelphij#define DPRINT_INTERFACE(level, args) do {} while (0) 237182007Sroberto#endif 238182007Sroberto 239132451Srobertotypedef struct vsock vsock_t; 240182007Srobertoenum desc_type { FD_TYPE_SOCKET, FD_TYPE_FILE }; 241132451Sroberto 242132451Srobertostruct vsock { 243285612Sdelphij vsock_t * link; 244285612Sdelphij SOCKET fd; 245285612Sdelphij enum desc_type type; 246132451Sroberto}; 247132451Sroberto 248285612Sdelphijvsock_t *fd_list; 249285612Sdelphij 250182007Sroberto#if !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) 251182007Sroberto/* 252182007Sroberto * async notification processing (e. g. routing sockets) 253182007Sroberto */ 254182007Sroberto/* 255182007Sroberto * support for receiving data on fd that is not a refclock or a socket 256182007Sroberto * like e. g. routing sockets 257182007Sroberto */ 258182007Srobertostruct asyncio_reader { 259285612Sdelphij struct asyncio_reader *link; /* the list this is being kept in */ 260285612Sdelphij SOCKET fd; /* fd to be read */ 261285612Sdelphij void *data; /* possibly local data */ 262182007Sroberto void (*receiver)(struct asyncio_reader *); /* input handler */ 263182007Sroberto}; 264132451Sroberto 265285612Sdelphijstruct asyncio_reader *asyncio_reader_list; 266182007Sroberto 267285612Sdelphijstatic void delete_asyncio_reader (struct asyncio_reader *); 268285612Sdelphijstatic struct asyncio_reader *new_asyncio_reader (void); 269285612Sdelphijstatic void add_asyncio_reader (struct asyncio_reader *, enum desc_type); 270285612Sdelphijstatic void remove_asyncio_reader (struct asyncio_reader *); 271182007Sroberto 272182007Sroberto#endif /* !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) */ 273182007Sroberto 274285612Sdelphijstatic void init_async_notifications (void); 275182007Sroberto 276285612Sdelphijstatic int addr_eqprefix (const sockaddr_u *, const sockaddr_u *, 277285612Sdelphij int); 278285612Sdelphijstatic int addr_samesubnet (const sockaddr_u *, const sockaddr_u *, 279285612Sdelphij const sockaddr_u *, const sockaddr_u *); 280285612Sdelphijstatic int create_sockets (u_short); 281285612Sdelphijstatic SOCKET open_socket (sockaddr_u *, int, int, endpt *); 282285612Sdelphijstatic void set_reuseaddr (int); 283285612Sdelphijstatic isc_boolean_t socket_broadcast_enable (struct interface *, SOCKET, sockaddr_u *); 284294569Sdelphij 285294569Sdelphij#if !defined(HAVE_IO_COMPLETION_PORT) && !defined(HAVE_SIGNALED_IO) 286294569Sdelphijstatic char * fdbits (int, const fd_set *); 287294569Sdelphij#endif 288285612Sdelphij#ifdef OS_MISSES_SPECIFIC_ROUTE_UPDATES 289285612Sdelphijstatic isc_boolean_t socket_broadcast_disable (struct interface *, sockaddr_u *); 290285612Sdelphij#endif 291182007Sroberto 292132451Srobertotypedef struct remaddr remaddr_t; 293132451Sroberto 294132451Srobertostruct remaddr { 295285612Sdelphij remaddr_t * link; 296285612Sdelphij sockaddr_u addr; 297285612Sdelphij endpt * ep; 298132451Sroberto}; 299132451Sroberto 300285612Sdelphijremaddr_t * remoteaddr_list; 301285612Sdelphijendpt * ep_list; /* complete endpt list */ 302285612Sdelphijendpt * mc4_list; /* IPv4 mcast-capable unicast endpts */ 303285612Sdelphijendpt * mc6_list; /* IPv6 mcast-capable unicast endpts */ 304132451Sroberto 305285612Sdelphijstatic endpt * wildipv4; 306285612Sdelphijstatic endpt * wildipv6; 307132451Sroberto 308285612Sdelphij#ifdef SYS_WINNT 309285612Sdelphijint accept_wildcard_if_for_winnt; 310285612Sdelphij#else 311285612Sdelphijconst int accept_wildcard_if_for_winnt = FALSE; 312285612Sdelphij#endif 313182007Sroberto 314285612Sdelphijstatic void add_fd_to_list (SOCKET, enum desc_type); 315285612Sdelphijstatic endpt * find_addr_in_list (sockaddr_u *); 316285612Sdelphijstatic endpt * find_flagged_addr_in_list(sockaddr_u *, u_int32); 317285612Sdelphijstatic void delete_addr_from_list (sockaddr_u *); 318285612Sdelphijstatic void delete_interface_from_list(endpt *); 319285612Sdelphijstatic void close_and_delete_fd_from_list(SOCKET); 320285612Sdelphijstatic void add_addr_to_list (sockaddr_u *, endpt *); 321285612Sdelphijstatic void create_wildcards (u_short); 322285612Sdelphijstatic endpt * findlocalinterface (sockaddr_u *, int, int); 323285612Sdelphijstatic endpt * findclosestinterface (sockaddr_u *, int); 324285612Sdelphij#ifdef DEBUG 325285612Sdelphijstatic const char * action_text (nic_rule_action); 326285612Sdelphij#endif 327285612Sdelphijstatic nic_rule_action interface_action(char *, sockaddr_u *, u_int32); 328285612Sdelphijstatic void convert_isc_if (isc_interface_t *, 329285612Sdelphij endpt *, u_short); 330285612Sdelphijstatic void calc_addr_distance(sockaddr_u *, 331285612Sdelphij const sockaddr_u *, 332285612Sdelphij const sockaddr_u *); 333285612Sdelphijstatic int cmp_addr_distance(const sockaddr_u *, 334285612Sdelphij const sockaddr_u *); 335182007Sroberto 336182007Sroberto/* 337182007Sroberto * Routines to read the ntp packets 338182007Sroberto */ 339182007Sroberto#if !defined(HAVE_IO_COMPLETION_PORT) 340285612Sdelphijstatic inline int read_network_packet (SOCKET, struct interface *, l_fp); 341285612Sdelphijstatic void ntpd_addremove_io_fd (int, int, int); 342294569Sdelphijstatic void input_handler_scan (const l_fp*, const fd_set*); 343294569Sdelphijstatic int/*BOOL*/ sanitize_fdset (int errc); 344285612Sdelphij#ifdef REFCLOCK 345285612Sdelphijstatic inline int read_refclock_packet (SOCKET, struct refclockio *, l_fp); 346182007Sroberto#endif 347294569Sdelphij#ifdef HAVE_SIGNALED_IO 348294569Sdelphijstatic void input_handler (l_fp*); 349285612Sdelphij#endif 350294569Sdelphij#endif 351182007Sroberto 352285612Sdelphij 353285612Sdelphij#ifndef HAVE_IO_COMPLETION_PORT 354200576Srobertovoid 355285612Sdelphijmaintain_activefds( 356285612Sdelphij int fd, 357285612Sdelphij int closing 358200576Sroberto ) 359200576Sroberto{ 360285612Sdelphij int i; 361132451Sroberto 362285612Sdelphij if (fd < 0 || fd >= FD_SETSIZE) { 363285612Sdelphij msyslog(LOG_ERR, 364285612Sdelphij "Too many sockets in use, FD_SETSIZE %d exceeded by fd %d", 365285612Sdelphij FD_SETSIZE, fd); 366285612Sdelphij exit(1); 367200576Sroberto } 368182007Sroberto 369285612Sdelphij if (!closing) { 370285612Sdelphij FD_SET(fd, &activefds); 371285612Sdelphij maxactivefd = max(fd, maxactivefd); 372285612Sdelphij } else { 373285612Sdelphij FD_CLR(fd, &activefds); 374285612Sdelphij if (maxactivefd && fd == maxactivefd) { 375285612Sdelphij for (i = maxactivefd - 1; i >= 0; i--) 376285612Sdelphij if (FD_ISSET(i, &activefds)) { 377285612Sdelphij maxactivefd = i; 378285612Sdelphij break; 379285612Sdelphij } 380289997Sglebius INSIST(fd != maxactivefd); 381285612Sdelphij } 382182007Sroberto } 383182007Sroberto} 384285612Sdelphij#endif /* !HAVE_IO_COMPLETION_PORT */ 385182007Sroberto 386285612Sdelphij 387182007Sroberto#ifdef DEBUG_TIMING 388182007Sroberto/* 389182007Sroberto * collect timing information for various processing 390285612Sdelphij * paths. currently we only pass them on to the file 391182007Sroberto * for later processing. this could also do histogram 392182007Sroberto * based analysis in other to reduce the load (and skew) 393182007Sroberto * dur to the file output 394182007Sroberto */ 395182007Srobertovoid 396182007Srobertocollect_timing(struct recvbuf *rb, const char *tag, int count, l_fp *dts) 397182007Sroberto{ 398285612Sdelphij char buf[256]; 399182007Sroberto 400285612Sdelphij snprintf(buf, sizeof(buf), "%s %d %s %s", 401285612Sdelphij (rb != NULL) 402285612Sdelphij ? ((rb->dstadr != NULL) 403285612Sdelphij ? stoa(&rb->recv_srcadr) 404285612Sdelphij : "-REFCLOCK-") 405285612Sdelphij : "-", 406182007Sroberto count, lfptoa(dts, 9), tag); 407182007Sroberto record_timing_stats(buf); 408182007Sroberto} 409182007Sroberto#endif 410285612Sdelphij 411182007Sroberto/* 412182007Sroberto * About dynamic interfaces, sockets, reception and more... 413182007Sroberto * 414182007Sroberto * the code solves following tasks: 415182007Sroberto * 416182007Sroberto * - keep a current list of active interfaces in order 417182007Sroberto * to bind to to the interface address on NTP_PORT so that 418182007Sroberto * all wild and specific bindings for NTP_PORT are taken by ntpd 419182007Sroberto * to avoid other daemons messing with the time or sockets. 420285612Sdelphij * - all interfaces keep a list of peers that are referencing 421182007Sroberto * the interface in order to quickly re-assign the peers to 422182007Sroberto * new interface in case an interface is deleted (=> gone from system or 423182007Sroberto * down) 424182007Sroberto * - have a preconfigured socket ready with the right local address 425182007Sroberto * for transmission and reception 426182007Sroberto * - have an address list for all destination addresses used within ntpd 427182007Sroberto * to find the "right" preconfigured socket. 428182007Sroberto * - facilitate updating the internal interface list with respect to 429182007Sroberto * the current kernel state 430182007Sroberto * 431182007Sroberto * special issues: 432182007Sroberto * 433182007Sroberto * - mapping of multicast addresses to the interface affected is not always 434182007Sroberto * one to one - especially on hosts with multiple interfaces 435182007Sroberto * the code here currently allocates a separate interface entry for those 436182007Sroberto * multicast addresses 437182007Sroberto * iff it is able to bind to a *new* socket with the multicast address (flags |= MCASTIF) 438182007Sroberto * in case of failure the multicast address is bound to an existing interface. 439182007Sroberto * - on some systems it is perfectly legal to assign the same address to 440182007Sroberto * multiple interfaces. Therefore this code does not keep a list of interfaces 441182007Sroberto * but a list of interfaces that represent a unique address as determined by the kernel 442182007Sroberto * by the procedure in findlocalinterface. Thus it is perfectly legal to see only 443182007Sroberto * one representative of a group of real interfaces if they share the same address. 444285612Sdelphij * 445182007Sroberto * Frank Kardel 20050910 446182007Sroberto */ 447182007Sroberto 448182007Sroberto/* 449285612Sdelphij * init_io - initialize I/O module. 45054359Sroberto */ 45154359Srobertovoid 45254359Srobertoinit_io(void) 45354359Sroberto{ 454285612Sdelphij /* Init buffer free list and stat counters */ 45554359Sroberto init_recvbuff(RECV_INIT); 456285612Sdelphij /* update interface every 5 minutes as default */ 457285612Sdelphij interface_interval = 300; 45854359Sroberto 459285612Sdelphij#ifdef WORK_PIPE 460285612Sdelphij addremove_io_fd = &ntpd_addremove_io_fd; 461285612Sdelphij#endif 46254359Sroberto 463294569Sdelphij#if defined(SYS_WINNT) 464285612Sdelphij init_io_completion_port(); 465294569Sdelphij#elif defined(HAVE_SIGNALED_IO) 466285612Sdelphij (void) set_signal(input_handler); 46754359Sroberto#endif 468285612Sdelphij} 46954359Sroberto 47054359Sroberto 471285612Sdelphijstatic void 472285612Sdelphijntpd_addremove_io_fd( 473285612Sdelphij int fd, 474285612Sdelphij int is_pipe, 475285612Sdelphij int remove_it 476285612Sdelphij ) 477285612Sdelphij{ 478285612Sdelphij UNUSED_ARG(is_pipe); 479132451Sroberto 480285612Sdelphij#ifdef HAVE_SIGNALED_IO 481294569Sdelphij if (!remove_it) 482294569Sdelphij init_socket_sig(fd); 483285612Sdelphij#endif /* not HAVE_SIGNALED_IO */ 484132451Sroberto 485285612Sdelphij maintain_activefds(fd, remove_it); 486285612Sdelphij} 487182007Sroberto 488285612Sdelphij 489285612Sdelphij/* 490285612Sdelphij * io_open_sockets - call socket creation routine 491285612Sdelphij */ 492285612Sdelphijvoid 493285612Sdelphijio_open_sockets(void) 494285612Sdelphij{ 495285612Sdelphij static int already_opened; 496285612Sdelphij 497285612Sdelphij if (already_opened || HAVE_OPT( SAVECONFIGQUIT )) 498285612Sdelphij return; 499285612Sdelphij 500285612Sdelphij already_opened = 1; 501285612Sdelphij 50254359Sroberto /* 50354359Sroberto * Create the sockets 50454359Sroberto */ 50554359Sroberto BLOCKIO(); 506285612Sdelphij create_sockets(NTP_PORT); 50754359Sroberto UNBLOCKIO(); 50854359Sroberto 509182007Sroberto init_async_notifications(); 510182007Sroberto 511285612Sdelphij DPRINTF(3, ("io_open_sockets: maxactivefd %d\n", maxactivefd)); 512182007Sroberto} 513182007Sroberto 514285612Sdelphij 51554359Sroberto#ifdef DEBUG 516182007Sroberto/* 517182007Sroberto * function to dump the contents of the interface structure 518182007Sroberto * for debugging use only. 519316069Sdelphij * We face a dilemma here -- sockets are FDs under POSIX and 520316069Sdelphij * actually HANDLES under Windows. So we use '%lld' as format 521316069Sdelphij * and cast the value to 'long long'; this should not hurt 522316069Sdelphij * with UNIX-like systems and does not truncate values on Win64. 523182007Sroberto */ 524182007Srobertovoid 525285612Sdelphijinterface_dump(const endpt *itf) 526182007Sroberto{ 527182007Sroberto printf("Dumping interface: %p\n", itf); 528316069Sdelphij printf("fd = %lld\n", (long long)itf->fd); 529316069Sdelphij printf("bfd = %lld\n", (long long)itf->bfd); 530285612Sdelphij printf("sin = %s,\n", stoa(&itf->sin)); 531285612Sdelphij sockaddr_dump(&itf->sin); 532285612Sdelphij printf("bcast = %s,\n", stoa(&itf->bcast)); 533285612Sdelphij sockaddr_dump(&itf->bcast); 534285612Sdelphij printf("mask = %s,\n", stoa(&itf->mask)); 535285612Sdelphij sockaddr_dump(&itf->mask); 536182007Sroberto printf("name = %s\n", itf->name); 537182007Sroberto printf("flags = 0x%08x\n", itf->flags); 538182007Sroberto printf("last_ttl = %d\n", itf->last_ttl); 539182007Sroberto printf("addr_refid = %08x\n", itf->addr_refid); 540182007Sroberto printf("num_mcast = %d\n", itf->num_mcast); 541182007Sroberto printf("received = %ld\n", itf->received); 542182007Sroberto printf("sent = %ld\n", itf->sent); 543182007Sroberto printf("notsent = %ld\n", itf->notsent); 544182007Sroberto printf("ifindex = %u\n", itf->ifindex); 545182007Sroberto printf("peercnt = %u\n", itf->peercnt); 546182007Sroberto printf("phase = %u\n", itf->phase); 547182007Sroberto} 548182007Sroberto 549182007Sroberto/* 550285612Sdelphij * sockaddr_dump - hex dump the start of a sockaddr_u 551285612Sdelphij */ 552285612Sdelphijstatic void 553285612Sdelphijsockaddr_dump(const sockaddr_u *psau) 554285612Sdelphij{ 555285612Sdelphij /* Limit the size of the sockaddr_in6 hex dump */ 556285612Sdelphij const int maxsize = min(32, sizeof(psau->sa6)); 557285612Sdelphij const u_char * cp; 558285612Sdelphij int i; 559285612Sdelphij 560285612Sdelphij /* XXX: Should we limit maxsize based on psau->saX.sin_family? */ 561285612Sdelphij cp = (const void *)&psau->sa6; 562285612Sdelphij 563285612Sdelphij for(i = 0; i < maxsize; i++) { 564285612Sdelphij printf("%02x", *cp++); 565285612Sdelphij if (!((i + 1) % 4)) 566285612Sdelphij printf(" "); 567285612Sdelphij } 568285612Sdelphij printf("\n"); 569285612Sdelphij} 570285612Sdelphij 571285612Sdelphij/* 572182007Sroberto * print_interface - helper to output debug information 573182007Sroberto */ 574182007Srobertostatic void 575285612Sdelphijprint_interface(const endpt *iface, const char *pfx, const char *sfx) 576182007Sroberto{ 577316069Sdelphij printf("%sinterface #%d: fd=%lld, bfd=%lld, name=%s, flags=0x%x, ifindex=%u, sin=%s", 578182007Sroberto pfx, 579182007Sroberto iface->ifnum, 580316069Sdelphij (long long)iface->fd, 581316069Sdelphij (long long)iface->bfd, 582182007Sroberto iface->name, 583182007Sroberto iface->flags, 584285612Sdelphij iface->ifindex, 585285612Sdelphij stoa(&iface->sin)); 586285612Sdelphij if (AF_INET == iface->family) { 587285612Sdelphij if (iface->flags & INT_BROADCAST) 588285612Sdelphij printf(", bcast=%s", stoa(&iface->bcast)); 589285612Sdelphij printf(", mask=%s", stoa(&iface->mask)); 590285612Sdelphij } 591285612Sdelphij printf(", %s:%s", 592285612Sdelphij (iface->ignore_packets) 593285612Sdelphij ? "Disabled" 594285612Sdelphij : "Enabled", 595285612Sdelphij sfx); 596182007Sroberto if (debug > 4) /* in-depth debugging only */ 597182007Sroberto interface_dump(iface); 598182007Sroberto} 59954359Sroberto#endif 600182007Sroberto 601182007Sroberto#if !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) 602182007Sroberto/* 603182007Sroberto * create an asyncio_reader structure 604182007Sroberto */ 605182007Srobertostatic struct asyncio_reader * 606285612Sdelphijnew_asyncio_reader(void) 607182007Sroberto{ 608182007Sroberto struct asyncio_reader *reader; 609182007Sroberto 610285612Sdelphij reader = emalloc_zero(sizeof(*reader)); 611285612Sdelphij reader->fd = INVALID_SOCKET; 612182007Sroberto 613182007Sroberto return reader; 61454359Sroberto} 61554359Sroberto 616182007Sroberto/* 617182007Sroberto * delete a reader 618182007Sroberto */ 619182007Srobertostatic void 620285612Sdelphijdelete_asyncio_reader( 621285612Sdelphij struct asyncio_reader *reader 622285612Sdelphij ) 623182007Sroberto{ 624182007Sroberto free(reader); 625182007Sroberto} 62654359Sroberto 627182007Sroberto/* 628182007Sroberto * add asynchio_reader 629182007Sroberto */ 630182007Srobertostatic void 631285612Sdelphijadd_asyncio_reader( 632285612Sdelphij struct asyncio_reader * reader, 633285612Sdelphij enum desc_type type) 634182007Sroberto{ 635285612Sdelphij LINK_SLIST(asyncio_reader_list, reader, link); 636182007Sroberto add_fd_to_list(reader->fd, type); 637182007Sroberto} 638285612Sdelphij 639182007Sroberto/* 640182007Sroberto * remove asynchio_reader 641182007Sroberto */ 642182007Srobertostatic void 643285612Sdelphijremove_asyncio_reader( 644285612Sdelphij struct asyncio_reader *reader 645285612Sdelphij ) 646182007Sroberto{ 647285612Sdelphij struct asyncio_reader *unlinked; 648182007Sroberto 649285612Sdelphij UNLINK_SLIST(unlinked, asyncio_reader_list, reader, link, 650285612Sdelphij struct asyncio_reader); 651285612Sdelphij 652182007Sroberto if (reader->fd != INVALID_SOCKET) 653182007Sroberto close_and_delete_fd_from_list(reader->fd); 654182007Sroberto 655182007Sroberto reader->fd = INVALID_SOCKET; 656182007Sroberto} 657182007Sroberto#endif /* !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) */ 658182007Sroberto 659285612Sdelphij 660285612Sdelphij/* compare two sockaddr prefixes */ 661285612Sdelphijstatic int 662285612Sdelphijaddr_eqprefix( 663285612Sdelphij const sockaddr_u * a, 664285612Sdelphij const sockaddr_u * b, 665285612Sdelphij int prefixlen 666285612Sdelphij ) 667285612Sdelphij{ 668285612Sdelphij isc_netaddr_t isc_a; 669285612Sdelphij isc_netaddr_t isc_b; 670285612Sdelphij isc_sockaddr_t isc_sa; 671285612Sdelphij 672285612Sdelphij ZERO(isc_sa); 673285612Sdelphij memcpy(&isc_sa.type, a, min(sizeof(isc_sa.type), sizeof(*a))); 674285612Sdelphij isc_netaddr_fromsockaddr(&isc_a, &isc_sa); 675285612Sdelphij 676285612Sdelphij ZERO(isc_sa); 677285612Sdelphij memcpy(&isc_sa.type, b, min(sizeof(isc_sa.type), sizeof(*b))); 678285612Sdelphij isc_netaddr_fromsockaddr(&isc_b, &isc_sa); 679285612Sdelphij 680285612Sdelphij return (int)isc_netaddr_eqprefix(&isc_a, &isc_b, 681285612Sdelphij (u_int)prefixlen); 682285612Sdelphij} 683285612Sdelphij 684285612Sdelphij 685285612Sdelphijstatic int 686285612Sdelphijaddr_samesubnet( 687285612Sdelphij const sockaddr_u * a, 688285612Sdelphij const sockaddr_u * a_mask, 689285612Sdelphij const sockaddr_u * b, 690285612Sdelphij const sockaddr_u * b_mask 691285612Sdelphij ) 692285612Sdelphij{ 693285612Sdelphij const u_int32 * pa; 694285612Sdelphij const u_int32 * pa_limit; 695285612Sdelphij const u_int32 * pb; 696285612Sdelphij const u_int32 * pm; 697285612Sdelphij size_t loops; 698285612Sdelphij 699289997Sglebius REQUIRE(AF(a) == AF(a_mask)); 700289997Sglebius REQUIRE(AF(b) == AF(b_mask)); 701285612Sdelphij /* 702285612Sdelphij * With address and mask families verified to match, comparing 703285612Sdelphij * the masks also validates the address's families match. 704285612Sdelphij */ 705285612Sdelphij if (!SOCK_EQ(a_mask, b_mask)) 706285612Sdelphij return FALSE; 707285612Sdelphij 708285612Sdelphij if (IS_IPV6(a)) { 709285612Sdelphij loops = sizeof(NSRCADR6(a)) / sizeof(*pa); 710285612Sdelphij pa = (const void *)&NSRCADR6(a); 711285612Sdelphij pb = (const void *)&NSRCADR6(b); 712285612Sdelphij pm = (const void *)&NSRCADR6(a_mask); 713285612Sdelphij } else { 714285612Sdelphij loops = sizeof(NSRCADR(a)) / sizeof(*pa); 715285612Sdelphij pa = (const void *)&NSRCADR(a); 716285612Sdelphij pb = (const void *)&NSRCADR(b); 717285612Sdelphij pm = (const void *)&NSRCADR(a_mask); 718285612Sdelphij } 719285612Sdelphij for (pa_limit = pa + loops; pa < pa_limit; pa++, pb++, pm++) 720285612Sdelphij if ((*pa & *pm) != (*pb & *pm)) 721285612Sdelphij return FALSE; 722285612Sdelphij 723285612Sdelphij return TRUE; 724285612Sdelphij} 725285612Sdelphij 726285612Sdelphij 727182007Sroberto/* 728182007Sroberto * interface list enumerator - visitor pattern 729182007Sroberto */ 730182007Srobertovoid 731285612Sdelphijinterface_enumerate( 732285612Sdelphij interface_receiver_t receiver, 733285612Sdelphij void * data 734285612Sdelphij ) 735182007Sroberto{ 736182007Sroberto interface_info_t ifi; 737182007Sroberto 738182007Sroberto ifi.action = IFS_EXISTS; 739285612Sdelphij for (ifi.ep = ep_list; ifi.ep != NULL; ifi.ep = ifi.ep->elink) 740285612Sdelphij (*receiver)(data, &ifi); 741182007Sroberto} 742182007Sroberto 743182007Sroberto/* 744182007Sroberto * do standard initialization of interface structure 745182007Sroberto */ 746182007Srobertostatic void 747285612Sdelphijinit_interface( 748285612Sdelphij endpt *ep 749285612Sdelphij ) 750182007Sroberto{ 751285612Sdelphij ZERO(*ep); 752285612Sdelphij ep->fd = INVALID_SOCKET; 753285612Sdelphij ep->bfd = INVALID_SOCKET; 754285612Sdelphij ep->phase = sys_interphase; 755182007Sroberto} 756182007Sroberto 757285612Sdelphij 758182007Sroberto/* 759182007Sroberto * create new interface structure initialize from 760182007Sroberto * template structure or via standard initialization 761182007Sroberto * function 762182007Sroberto */ 763182007Srobertostatic struct interface * 764285612Sdelphijnew_interface( 765285612Sdelphij struct interface *interface 766285612Sdelphij ) 767182007Sroberto{ 768285612Sdelphij struct interface * iface; 769182007Sroberto 770285612Sdelphij iface = emalloc(sizeof(*iface)); 771182007Sroberto 772285612Sdelphij if (NULL == interface) 773182007Sroberto init_interface(iface); 774285612Sdelphij else /* use the template */ 775285612Sdelphij memcpy(iface, interface, sizeof(*iface)); 776182007Sroberto 777285612Sdelphij /* count every new instance of an interface in the system */ 778285612Sdelphij iface->ifnum = sys_ifnum++; 779182007Sroberto iface->starttime = current_time; 780182007Sroberto 781298699Sdelphij# ifdef HAVE_IO_COMPLETION_PORT 782298699Sdelphij if (!io_completion_port_add_interface(iface)) { 783298699Sdelphij msyslog(LOG_EMERG, "cannot register interface with IO engine -- will exit now"); 784298699Sdelphij exit(1); 785298699Sdelphij } 786298699Sdelphij# endif 787182007Sroberto return iface; 788182007Sroberto} 789182007Sroberto 790285612Sdelphij 791182007Sroberto/* 792182007Sroberto * return interface storage into free memory pool 793182007Sroberto */ 794298699Sdelphijstatic void 795285612Sdelphijdelete_interface( 796285612Sdelphij endpt *ep 797285612Sdelphij ) 798182007Sroberto{ 799298699Sdelphij# ifdef HAVE_IO_COMPLETION_PORT 800298699Sdelphij io_completion_port_remove_interface(ep); 801298699Sdelphij# endif 802285612Sdelphij free(ep); 803182007Sroberto} 804182007Sroberto 805285612Sdelphij 806182007Sroberto/* 807182007Sroberto * link interface into list of known interfaces 808182007Sroberto */ 809182007Srobertostatic void 810285612Sdelphijadd_interface( 811285612Sdelphij endpt * ep 812285612Sdelphij ) 813182007Sroberto{ 814285612Sdelphij endpt ** pmclisthead; 815285612Sdelphij endpt * scan; 816285612Sdelphij endpt * scan_next; 817285612Sdelphij endpt * unlinked; 818285612Sdelphij sockaddr_u * addr; 819285612Sdelphij int ep_local; 820285612Sdelphij int scan_local; 821285612Sdelphij int same_subnet; 822285612Sdelphij int ep_univ_iid; /* iface ID from MAC address */ 823285612Sdelphij int scan_univ_iid; /* see RFC 4291 */ 824285612Sdelphij int ep_privacy; /* random local iface ID */ 825285612Sdelphij int scan_privacy; /* see RFC 4941 */ 826285612Sdelphij int rc; 827200576Sroberto 828285612Sdelphij /* Calculate the refid */ 829285612Sdelphij ep->addr_refid = addr2refid(&ep->sin); 830285612Sdelphij /* link at tail so ntpdc -c ifstats index increases each row */ 831285612Sdelphij LINK_TAIL_SLIST(ep_list, ep, elink, endpt); 832285612Sdelphij ninterfaces++; 833285612Sdelphij#ifdef MCAST 834285612Sdelphij /* the rest is for enabled multicast-capable addresses only */ 835285612Sdelphij if (ep->ignore_packets || !(INT_MULTICAST & ep->flags) || 836285612Sdelphij INT_LOOPBACK & ep->flags) 837285612Sdelphij return; 838285612Sdelphij# ifndef INCLUDE_IPV6_MULTICAST_SUPPORT 839285612Sdelphij if (AF_INET6 == ep->family) 840285612Sdelphij return; 841285612Sdelphij# endif 842285612Sdelphij pmclisthead = (AF_INET == ep->family) 843285612Sdelphij ? &mc4_list 844285612Sdelphij : &mc6_list; 845285612Sdelphij 846285612Sdelphij if (AF_INET6 == ep->family) { 847285612Sdelphij ep_local = 848285612Sdelphij IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(&ep->sin)) || 849285612Sdelphij IN6_IS_ADDR_SITELOCAL(PSOCK_ADDR6(&ep->sin)); 850285612Sdelphij ep_univ_iid = IS_IID_UNIV(&ep->sin); 851285612Sdelphij ep_privacy = !!(INT_PRIVACY & ep->flags); 852285612Sdelphij } else { 853285612Sdelphij ep_local = FALSE; 854285612Sdelphij ep_univ_iid = FALSE; 855285612Sdelphij ep_privacy = FALSE; 856285612Sdelphij } 857285612Sdelphij DPRINTF(4, ("add_interface mcast-capable %s%s%s%s\n", 858285612Sdelphij stoa(&ep->sin), 859285612Sdelphij (ep_local) ? " link/scope-local" : "", 860285612Sdelphij (ep_univ_iid) ? " univ-IID" : "", 861285612Sdelphij (ep_privacy) ? " privacy" : "")); 862132451Sroberto /* 863285612Sdelphij * If we have multiple local addresses on the same network 864285612Sdelphij * interface, and some are link- or site-local, do not multicast 865285612Sdelphij * out from the link-/site-local addresses by default, to avoid 866285612Sdelphij * duplicate manycastclient associations between v6 peers using 867285612Sdelphij * link-local and global addresses. link-local can still be 868285612Sdelphij * chosen using "nic ignore myv6globalprefix::/64". 869285612Sdelphij * Similarly, if we have multiple global addresses from the same 870285612Sdelphij * prefix on the same network interface, multicast from one, 871285612Sdelphij * preferring EUI-64, then static, then least RFC 4941 privacy 872285612Sdelphij * addresses. 873200576Sroberto */ 874285612Sdelphij for (scan = *pmclisthead; scan != NULL; scan = scan_next) { 875285612Sdelphij scan_next = scan->mclink; 876285612Sdelphij if (ep->family != scan->family) 877285612Sdelphij continue; 878285612Sdelphij if (strcmp(ep->name, scan->name)) 879285612Sdelphij continue; 880285612Sdelphij same_subnet = addr_samesubnet(&ep->sin, &ep->mask, 881285612Sdelphij &scan->sin, &scan->mask); 882285612Sdelphij if (AF_INET6 == ep->family) { 883285612Sdelphij addr = &scan->sin; 884285612Sdelphij scan_local = 885285612Sdelphij IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(addr)) || 886285612Sdelphij IN6_IS_ADDR_SITELOCAL(PSOCK_ADDR6(addr)); 887285612Sdelphij scan_univ_iid = IS_IID_UNIV(addr); 888285612Sdelphij scan_privacy = !!(INT_PRIVACY & scan->flags); 889285612Sdelphij } else { 890285612Sdelphij scan_local = FALSE; 891285612Sdelphij scan_univ_iid = FALSE; 892285612Sdelphij scan_privacy = FALSE; 893285612Sdelphij } 894285612Sdelphij DPRINTF(4, ("add_interface mcast-capable scan %s%s%s%s\n", 895285612Sdelphij stoa(&scan->sin), 896285612Sdelphij (scan_local) ? " link/scope-local" : "", 897285612Sdelphij (scan_univ_iid) ? " univ-IID" : "", 898285612Sdelphij (scan_privacy) ? " privacy" : "")); 899285612Sdelphij if ((ep_local && !scan_local) || (same_subnet && 900285612Sdelphij ((ep_privacy && !scan_privacy) || 901285612Sdelphij (!ep_univ_iid && scan_univ_iid)))) { 902285612Sdelphij DPRINTF(4, ("did not add %s to %s of IPv6 multicast-capable list which already has %s\n", 903285612Sdelphij stoa(&ep->sin), 904285612Sdelphij (ep_local) 905285612Sdelphij ? "tail" 906285612Sdelphij : "head", 907285612Sdelphij stoa(&scan->sin))); 908285612Sdelphij return; 909285612Sdelphij } 910285612Sdelphij if ((scan_local && !ep_local) || (same_subnet && 911285612Sdelphij ((scan_privacy && !ep_privacy) || 912285612Sdelphij (!scan_univ_iid && ep_univ_iid)))) { 913285612Sdelphij UNLINK_SLIST(unlinked, *pmclisthead, 914285612Sdelphij scan, mclink, endpt); 915285612Sdelphij DPRINTF(4, ("%s %s from IPv6 multicast-capable list to add %s\n", 916285612Sdelphij (unlinked != scan) 917285612Sdelphij ? "Failed to remove" 918285612Sdelphij : "removed", 919285612Sdelphij stoa(&scan->sin), stoa(&ep->sin))); 920285612Sdelphij } 921200576Sroberto } 922200576Sroberto /* 923285612Sdelphij * Add link/site local at the tail of the multicast- 924285612Sdelphij * capable unicast interfaces list, so that ntpd will 925285612Sdelphij * send from global addresses before link-/site-local 926285612Sdelphij * ones. 927182007Sroberto */ 928285612Sdelphij if (ep_local) 929285612Sdelphij LINK_TAIL_SLIST(*pmclisthead, ep, mclink, endpt); 930285612Sdelphij else 931285612Sdelphij LINK_SLIST(*pmclisthead, ep, mclink); 932285612Sdelphij DPRINTF(4, ("added %s to %s of IPv%s multicast-capable unicast local address list\n", 933285612Sdelphij stoa(&ep->sin), 934285612Sdelphij (ep_local) 935285612Sdelphij ? "tail" 936285612Sdelphij : "head", 937285612Sdelphij (AF_INET == ep->family) 938285612Sdelphij ? "4" 939285612Sdelphij : "6")); 940285612Sdelphij 941285612Sdelphij if (INVALID_SOCKET == ep->fd) 942285612Sdelphij return; 943285612Sdelphij 944285612Sdelphij /* 945285612Sdelphij * select the local address from which to send to multicast. 946285612Sdelphij */ 947285612Sdelphij switch (AF(&ep->sin)) { 948285612Sdelphij 949285612Sdelphij case AF_INET : 950285612Sdelphij rc = setsockopt(ep->fd, IPPROTO_IP, 951285612Sdelphij IP_MULTICAST_IF, 952285612Sdelphij (void *)&NSRCADR(&ep->sin), 953285612Sdelphij sizeof(NSRCADR(&ep->sin))); 954285612Sdelphij if (rc) 955285612Sdelphij msyslog(LOG_ERR, 956285612Sdelphij "setsockopt IP_MULTICAST_IF %s fails: %m", 957285612Sdelphij stoa(&ep->sin)); 958285612Sdelphij break; 959285612Sdelphij 960285612Sdelphij# ifdef INCLUDE_IPV6_MULTICAST_SUPPORT 961285612Sdelphij case AF_INET6 : 962285612Sdelphij rc = setsockopt(ep->fd, IPPROTO_IPV6, 963285612Sdelphij IPV6_MULTICAST_IF, 964285612Sdelphij (void *)&ep->ifindex, 965285612Sdelphij sizeof(ep->ifindex)); 966285612Sdelphij /* do not complain if bound addr scope is ifindex */ 967285612Sdelphij if (rc && ep->ifindex != SCOPE(&ep->sin)) 968285612Sdelphij msyslog(LOG_ERR, 969285612Sdelphij "setsockopt IPV6_MULTICAST_IF %u for %s fails: %m", 970285612Sdelphij ep->ifindex, stoa(&ep->sin)); 971285612Sdelphij break; 972285612Sdelphij# endif 973285612Sdelphij } 974285612Sdelphij#endif /* MCAST */ 975182007Sroberto} 976182007Sroberto 977285612Sdelphij 978182007Sroberto/* 979182007Sroberto * remove interface from known interface list and clean up 980182007Sroberto * associated resources 981182007Sroberto */ 982182007Srobertostatic void 983285612Sdelphijremove_interface( 984285612Sdelphij endpt * ep 985285612Sdelphij ) 986182007Sroberto{ 987285612Sdelphij endpt * unlinked; 988285612Sdelphij endpt ** pmclisthead; 989285612Sdelphij sockaddr_u resmask; 990182007Sroberto 991285612Sdelphij UNLINK_SLIST(unlinked, ep_list, ep, elink, endpt); 992285612Sdelphij if (!ep->ignore_packets && INT_MULTICAST & ep->flags) { 993285612Sdelphij pmclisthead = (AF_INET == ep->family) 994285612Sdelphij ? &mc4_list 995285612Sdelphij : &mc6_list; 996285612Sdelphij UNLINK_SLIST(unlinked, *pmclisthead, ep, mclink, endpt); 997285612Sdelphij DPRINTF(4, ("%s %s IPv%s multicast-capable unicast local address list\n", 998285612Sdelphij stoa(&ep->sin), 999285612Sdelphij (unlinked != NULL) 1000285612Sdelphij ? "removed from" 1001285612Sdelphij : "not found on", 1002285612Sdelphij (AF_INET == ep->family) 1003285612Sdelphij ? "4" 1004285612Sdelphij : "6")); 1005285612Sdelphij } 1006285612Sdelphij delete_interface_from_list(ep); 1007182007Sroberto 1008285612Sdelphij if (ep->fd != INVALID_SOCKET) { 1009285612Sdelphij msyslog(LOG_INFO, 1010285612Sdelphij "Deleting interface #%d %s, %s#%d, interface stats: received=%ld, sent=%ld, dropped=%ld, active_time=%ld secs", 1011285612Sdelphij ep->ifnum, 1012285612Sdelphij ep->name, 1013285612Sdelphij stoa(&ep->sin), 1014285612Sdelphij SRCPORT(&ep->sin), 1015285612Sdelphij ep->received, 1016285612Sdelphij ep->sent, 1017285612Sdelphij ep->notsent, 1018285612Sdelphij current_time - ep->starttime); 1019298699Sdelphij# ifdef HAVE_IO_COMPLETION_PORT 1020298699Sdelphij io_completion_port_remove_socket(ep->fd, ep); 1021298699Sdelphij# endif 1022285612Sdelphij close_and_delete_fd_from_list(ep->fd); 1023285612Sdelphij ep->fd = INVALID_SOCKET; 1024285612Sdelphij } 1025182007Sroberto 1026285612Sdelphij if (ep->bfd != INVALID_SOCKET) { 1027285612Sdelphij msyslog(LOG_INFO, 1028285612Sdelphij "stop listening for broadcasts to %s on interface #%d %s", 1029285612Sdelphij stoa(&ep->bcast), ep->ifnum, ep->name); 1030298699Sdelphij# ifdef HAVE_IO_COMPLETION_PORT 1031298699Sdelphij io_completion_port_remove_socket(ep->bfd, ep); 1032298699Sdelphij# endif 1033285612Sdelphij close_and_delete_fd_from_list(ep->bfd); 1034285612Sdelphij ep->bfd = INVALID_SOCKET; 1035182007Sroberto } 1036298699Sdelphij# ifdef HAVE_IO_COMPLETION_PORT 1037298699Sdelphij io_completion_port_remove_interface(ep); 1038298699Sdelphij# endif 1039182007Sroberto 1040182007Sroberto ninterfaces--; 1041285612Sdelphij mon_clearinterface(ep); 1042182007Sroberto 1043182007Sroberto /* remove restrict interface entry */ 1044285612Sdelphij SET_HOSTMASK(&resmask, AF(&ep->sin)); 1045285612Sdelphij hack_restrict(RESTRICT_REMOVEIF, &ep->sin, &resmask, 1046330141Sdelphij -3, RESM_NTPONLY | RESM_INTERFACE, RES_IGNORE, 0); 1047182007Sroberto} 1048182007Sroberto 1049285612Sdelphij 1050182007Srobertostatic void 1051285612Sdelphijlog_listen_address( 1052285612Sdelphij endpt * ep 1053285612Sdelphij ) 1054182007Sroberto{ 1055285612Sdelphij msyslog(LOG_INFO, "%s on %d %s %s", 1056285612Sdelphij (ep->ignore_packets) 1057285612Sdelphij ? "Listen and drop" 1058285612Sdelphij : "Listen normally", 1059285612Sdelphij ep->ifnum, 1060285612Sdelphij ep->name, 1061285612Sdelphij sptoa(&ep->sin)); 1062182007Sroberto} 1063182007Sroberto 1064285612Sdelphij 1065182007Srobertostatic void 1066285612Sdelphijcreate_wildcards( 1067285612Sdelphij u_short port 1068285612Sdelphij ) 1069285612Sdelphij{ 1070285612Sdelphij int v4wild; 1071285612Sdelphij#ifdef INCLUDE_IPV6_SUPPORT 1072285612Sdelphij int v6wild; 1073285612Sdelphij#endif 1074285612Sdelphij sockaddr_u wildaddr; 1075285612Sdelphij nic_rule_action action; 1076285612Sdelphij struct interface * wildif; 1077285612Sdelphij 1078182007Sroberto /* 1079285612Sdelphij * silence "potentially uninitialized" warnings from VC9 1080285612Sdelphij * failing to follow the logic. Ideally action could remain 1081285612Sdelphij * uninitialized, and the memset be the first statement under 1082285612Sdelphij * the first if (v4wild). 1083132451Sroberto */ 1084285612Sdelphij action = ACTION_LISTEN; 1085285612Sdelphij ZERO(wildaddr); 1086182007Sroberto 1087285612Sdelphij#ifdef INCLUDE_IPV6_SUPPORT 1088285612Sdelphij /* 1089285612Sdelphij * create pseudo-interface with wildcard IPv6 address 1090285612Sdelphij */ 1091285612Sdelphij v6wild = ipv6_works; 1092285612Sdelphij if (v6wild) { 1093285612Sdelphij /* set wildaddr to the v6 wildcard address :: */ 1094285612Sdelphij ZERO(wildaddr); 1095285612Sdelphij AF(&wildaddr) = AF_INET6; 1096285612Sdelphij SET_ADDR6N(&wildaddr, in6addr_any); 1097285612Sdelphij SET_PORT(&wildaddr, port); 1098285612Sdelphij SET_SCOPE(&wildaddr, 0); 1099182007Sroberto 1100285612Sdelphij /* check for interface/nic rules affecting the wildcard */ 1101285612Sdelphij action = interface_action(NULL, &wildaddr, 0); 1102285612Sdelphij v6wild = (ACTION_IGNORE != action); 1103285612Sdelphij } 1104285612Sdelphij if (v6wild) { 1105285612Sdelphij wildif = new_interface(NULL); 110654359Sroberto 1107285612Sdelphij strlcpy(wildif->name, "v6wildcard", sizeof(wildif->name)); 1108285612Sdelphij memcpy(&wildif->sin, &wildaddr, sizeof(wildif->sin)); 1109285612Sdelphij wildif->family = AF_INET6; 1110285612Sdelphij AF(&wildif->mask) = AF_INET6; 1111285612Sdelphij SET_ONESMASK(&wildif->mask); 1112285612Sdelphij 1113285612Sdelphij wildif->flags = INT_UP | INT_WILDCARD; 1114285612Sdelphij wildif->ignore_packets = (ACTION_DROP == action); 1115285612Sdelphij 1116285612Sdelphij wildif->fd = open_socket(&wildif->sin, 0, 1, wildif); 1117285612Sdelphij 1118285612Sdelphij if (wildif->fd != INVALID_SOCKET) { 1119285612Sdelphij wildipv6 = wildif; 1120285612Sdelphij any6_interface = wildif; 1121285612Sdelphij add_addr_to_list(&wildif->sin, wildif); 1122285612Sdelphij add_interface(wildif); 1123285612Sdelphij log_listen_address(wildif); 1124182007Sroberto } else { 1125285612Sdelphij msyslog(LOG_ERR, 1126285612Sdelphij "unable to bind to wildcard address %s - another process may be running - EXITING", 1127285612Sdelphij stoa(&wildif->sin)); 1128182007Sroberto exit(1); 1129182007Sroberto } 1130285612Sdelphij DPRINT_INTERFACE(2, (wildif, "created ", "\n")); 1131182007Sroberto } 1132285612Sdelphij#endif 1133182007Sroberto 113454359Sroberto /* 1135285612Sdelphij * create pseudo-interface with wildcard IPv4 address 113654359Sroberto */ 1137285612Sdelphij v4wild = ipv4_works; 1138285612Sdelphij if (v4wild) { 1139285612Sdelphij /* set wildaddr to the v4 wildcard address 0.0.0.0 */ 1140285612Sdelphij AF(&wildaddr) = AF_INET; 1141285612Sdelphij SET_ADDR4N(&wildaddr, INADDR_ANY); 1142285612Sdelphij SET_PORT(&wildaddr, port); 1143182007Sroberto 1144285612Sdelphij /* check for interface/nic rules affecting the wildcard */ 1145285612Sdelphij action = interface_action(NULL, &wildaddr, 0); 1146285612Sdelphij v4wild = (ACTION_IGNORE != action); 1147285612Sdelphij } 1148285612Sdelphij if (v4wild) { 1149285612Sdelphij wildif = new_interface(NULL); 1150182007Sroberto 1151285612Sdelphij strlcpy(wildif->name, "v4wildcard", sizeof(wildif->name)); 1152285612Sdelphij memcpy(&wildif->sin, &wildaddr, sizeof(wildif->sin)); 1153285612Sdelphij wildif->family = AF_INET; 1154285612Sdelphij AF(&wildif->mask) = AF_INET; 1155285612Sdelphij SET_ONESMASK(&wildif->mask); 1156182007Sroberto 1157285612Sdelphij wildif->flags = INT_BROADCAST | INT_UP | INT_WILDCARD; 1158285612Sdelphij wildif->ignore_packets = (ACTION_DROP == action); 1159285612Sdelphij#if defined(MCAST) 1160285612Sdelphij /* 1161285612Sdelphij * enable multicast reception on the broadcast socket 1162285612Sdelphij */ 1163285612Sdelphij AF(&wildif->bcast) = AF_INET; 1164285612Sdelphij SET_ADDR4N(&wildif->bcast, INADDR_ANY); 1165285612Sdelphij SET_PORT(&wildif->bcast, port); 1166285612Sdelphij#endif /* MCAST */ 1167285612Sdelphij wildif->fd = open_socket(&wildif->sin, 0, 1, wildif); 1168285612Sdelphij 1169285612Sdelphij if (wildif->fd != INVALID_SOCKET) { 1170285612Sdelphij wildipv4 = wildif; 1171285612Sdelphij any_interface = wildif; 1172285612Sdelphij 1173285612Sdelphij add_addr_to_list(&wildif->sin, wildif); 1174285612Sdelphij add_interface(wildif); 1175285612Sdelphij log_listen_address(wildif); 1176182007Sroberto } else { 1177285612Sdelphij msyslog(LOG_ERR, 1178285612Sdelphij "unable to bind to wildcard address %s - another process may be running - EXITING", 1179285612Sdelphij stoa(&wildif->sin)); 1180182007Sroberto exit(1); 1181182007Sroberto } 1182285612Sdelphij DPRINT_INTERFACE(2, (wildif, "created ", "\n")); 118354359Sroberto } 1184132451Sroberto} 118554359Sroberto 118654359Sroberto 1187285612Sdelphij/* 1188285612Sdelphij * add_nic_rule() -- insert a rule entry at the head of nic_rule_list. 1189285612Sdelphij */ 1190285612Sdelphijvoid 1191285612Sdelphijadd_nic_rule( 1192285612Sdelphij nic_rule_match match_type, 1193285612Sdelphij const char * if_name, /* interface name or numeric address */ 1194285612Sdelphij int prefixlen, 1195285612Sdelphij nic_rule_action action 1196285612Sdelphij ) 1197285612Sdelphij{ 1198285612Sdelphij nic_rule * rule; 1199285612Sdelphij isc_boolean_t is_ip; 120054359Sroberto 1201285612Sdelphij rule = emalloc_zero(sizeof(*rule)); 1202285612Sdelphij rule->match_type = match_type; 1203285612Sdelphij rule->prefixlen = prefixlen; 1204285612Sdelphij rule->action = action; 120554359Sroberto 1206285612Sdelphij if (MATCH_IFNAME == match_type) { 1207289997Sglebius REQUIRE(NULL != if_name); 1208285612Sdelphij rule->if_name = estrdup(if_name); 1209285612Sdelphij } else if (MATCH_IFADDR == match_type) { 1210289997Sglebius REQUIRE(NULL != if_name); 1211285612Sdelphij /* set rule->addr */ 1212285612Sdelphij is_ip = is_ip_address(if_name, AF_UNSPEC, &rule->addr); 1213289997Sglebius REQUIRE(is_ip); 1214285612Sdelphij } else 1215289997Sglebius REQUIRE(NULL == if_name); 1216285612Sdelphij 1217285612Sdelphij LINK_SLIST(nic_rule_list, rule, next); 1218285612Sdelphij} 1219285612Sdelphij 1220285612Sdelphij 1221285612Sdelphij#ifdef DEBUG 1222285612Sdelphijstatic const char * 1223285612Sdelphijaction_text( 1224285612Sdelphij nic_rule_action action 1225285612Sdelphij ) 1226285612Sdelphij{ 1227285612Sdelphij const char *t; 1228285612Sdelphij 1229285612Sdelphij switch (action) { 1230285612Sdelphij 1231285612Sdelphij default: 1232285612Sdelphij t = "ERROR"; /* quiet uninit warning */ 1233285612Sdelphij DPRINTF(1, ("fatal: unknown nic_rule_action %d\n", 1234285612Sdelphij action)); 1235289997Sglebius ENSURE(0); 1236285612Sdelphij break; 1237285612Sdelphij 1238285612Sdelphij case ACTION_LISTEN: 1239285612Sdelphij t = "listen"; 1240285612Sdelphij break; 1241285612Sdelphij 1242285612Sdelphij case ACTION_IGNORE: 1243285612Sdelphij t = "ignore"; 1244285612Sdelphij break; 1245285612Sdelphij 1246285612Sdelphij case ACTION_DROP: 1247285612Sdelphij t = "drop"; 1248285612Sdelphij break; 1249285612Sdelphij } 1250285612Sdelphij 1251285612Sdelphij return t; 1252285612Sdelphij} 1253285612Sdelphij#endif /* DEBUG */ 1254285612Sdelphij 1255285612Sdelphij 1256285612Sdelphijstatic nic_rule_action 1257285612Sdelphijinterface_action( 1258285612Sdelphij char * if_name, 1259285612Sdelphij sockaddr_u * if_addr, 1260285612Sdelphij u_int32 if_flags 1261285612Sdelphij ) 1262285612Sdelphij{ 1263285612Sdelphij nic_rule * rule; 1264285612Sdelphij int isloopback; 1265285612Sdelphij int iswildcard; 1266285612Sdelphij 1267285612Sdelphij DPRINTF(4, ("interface_action: interface %s ", 1268285612Sdelphij (if_name != NULL) ? if_name : "wildcard")); 1269285612Sdelphij 1270285612Sdelphij iswildcard = is_wildcard_addr(if_addr); 1271285612Sdelphij isloopback = !!(INT_LOOPBACK & if_flags); 1272285612Sdelphij 1273182007Sroberto /* 1274285612Sdelphij * Find any matching NIC rule from --interface / -I or ntp.conf 1275285612Sdelphij * interface/nic rules. 1276132451Sroberto */ 1277285612Sdelphij for (rule = nic_rule_list; rule != NULL; rule = rule->next) { 1278285612Sdelphij 1279285612Sdelphij switch (rule->match_type) { 1280285612Sdelphij 1281285612Sdelphij case MATCH_ALL: 1282285612Sdelphij /* loopback and wildcard excluded from "all" */ 1283285612Sdelphij if (isloopback || iswildcard) 1284285612Sdelphij break; 1285285612Sdelphij DPRINTF(4, ("nic all %s\n", 1286285612Sdelphij action_text(rule->action))); 1287285612Sdelphij return rule->action; 1288285612Sdelphij 1289285612Sdelphij case MATCH_IPV4: 1290285612Sdelphij if (IS_IPV4(if_addr)) { 1291285612Sdelphij DPRINTF(4, ("nic ipv4 %s\n", 1292285612Sdelphij action_text(rule->action))); 1293285612Sdelphij return rule->action; 1294285612Sdelphij } 1295285612Sdelphij break; 1296285612Sdelphij 1297285612Sdelphij case MATCH_IPV6: 1298285612Sdelphij if (IS_IPV6(if_addr)) { 1299285612Sdelphij DPRINTF(4, ("nic ipv6 %s\n", 1300285612Sdelphij action_text(rule->action))); 1301285612Sdelphij return rule->action; 1302285612Sdelphij } 1303285612Sdelphij break; 1304285612Sdelphij 1305285612Sdelphij case MATCH_WILDCARD: 1306285612Sdelphij if (iswildcard) { 1307285612Sdelphij DPRINTF(4, ("nic wildcard %s\n", 1308285612Sdelphij action_text(rule->action))); 1309285612Sdelphij return rule->action; 1310285612Sdelphij } 1311285612Sdelphij break; 1312285612Sdelphij 1313285612Sdelphij case MATCH_IFADDR: 1314285612Sdelphij if (rule->prefixlen != -1) { 1315285612Sdelphij if (addr_eqprefix(if_addr, &rule->addr, 1316285612Sdelphij rule->prefixlen)) { 1317285612Sdelphij 1318285612Sdelphij DPRINTF(4, ("subnet address match - %s\n", 1319285612Sdelphij action_text(rule->action))); 1320285612Sdelphij return rule->action; 1321285612Sdelphij } 1322285612Sdelphij } else 1323285612Sdelphij if (SOCK_EQ(if_addr, &rule->addr)) { 1324285612Sdelphij 1325285612Sdelphij DPRINTF(4, ("address match - %s\n", 1326285612Sdelphij action_text(rule->action))); 1327285612Sdelphij return rule->action; 1328285612Sdelphij } 1329285612Sdelphij break; 1330285612Sdelphij 1331285612Sdelphij case MATCH_IFNAME: 1332285612Sdelphij if (if_name != NULL 1333285612Sdelphij#if defined(HAVE_FNMATCH) && defined(FNM_CASEFOLD) 1334285612Sdelphij && !fnmatch(rule->if_name, if_name, FNM_CASEFOLD) 1335285612Sdelphij#else 1336285612Sdelphij && !strcasecmp(if_name, rule->if_name) 1337285612Sdelphij#endif 1338285612Sdelphij ) { 1339285612Sdelphij 1340285612Sdelphij DPRINTF(4, ("interface name match - %s\n", 1341285612Sdelphij action_text(rule->action))); 1342285612Sdelphij return rule->action; 1343285612Sdelphij } 1344285612Sdelphij break; 1345285612Sdelphij } 1346182007Sroberto } 1347182007Sroberto 1348182007Sroberto /* 1349285612Sdelphij * Unless explicitly disabled such as with "nic ignore ::1" 1350285612Sdelphij * listen on loopback addresses. Since ntpq and ntpdc query 1351285612Sdelphij * "localhost" by default, which typically resolves to ::1 and 1352285612Sdelphij * 127.0.0.1, it's useful to default to listening on both. 1353182007Sroberto */ 1354285612Sdelphij if (isloopback) { 1355285612Sdelphij DPRINTF(4, ("default loopback listen\n")); 1356285612Sdelphij return ACTION_LISTEN; 1357182007Sroberto } 1358285612Sdelphij 1359285612Sdelphij /* 1360285612Sdelphij * Treat wildcard addresses specially. If there is no explicit 1361285612Sdelphij * "nic ... wildcard" or "nic ... 0.0.0.0" or "nic ... ::" rule 1362285612Sdelphij * default to drop. 1363285612Sdelphij */ 1364285612Sdelphij if (iswildcard) { 1365285612Sdelphij DPRINTF(4, ("default wildcard drop\n")); 1366285612Sdelphij return ACTION_DROP; 1367182007Sroberto } 1368182007Sroberto 1369285612Sdelphij /* 1370285612Sdelphij * Check for "virtual IP" (colon in the interface name) after 1371285612Sdelphij * the rules so that "ntpd --interface eth0:1 -novirtualips" 1372285612Sdelphij * does indeed listen on eth0:1's addresses. 1373285612Sdelphij */ 1374285612Sdelphij if (!listen_to_virtual_ips && if_name != NULL 1375285612Sdelphij && (strchr(if_name, ':') != NULL)) { 1376285612Sdelphij 1377285612Sdelphij DPRINTF(4, ("virtual ip - ignore\n")); 1378285612Sdelphij return ACTION_IGNORE; 1379285612Sdelphij } 1380285612Sdelphij 1381285612Sdelphij /* 1382285612Sdelphij * If there are no --interface/-I command-line options and no 1383285612Sdelphij * interface/nic rules in ntp.conf, the default action is to 1384285612Sdelphij * listen. In the presence of rules from either, the default 1385285612Sdelphij * is to ignore. This implements ntpd's traditional listen- 1386285612Sdelphij * every default with no interface listen configuration, and 1387285612Sdelphij * ensures a single -I eth0 or "nic listen eth0" means do not 1388285612Sdelphij * listen on any other addresses. 1389285612Sdelphij */ 1390285612Sdelphij if (NULL == nic_rule_list) { 1391285612Sdelphij DPRINTF(4, ("default listen\n")); 1392285612Sdelphij return ACTION_LISTEN; 1393285612Sdelphij } 1394285612Sdelphij 1395285612Sdelphij DPRINTF(4, ("implicit ignore\n")); 1396285612Sdelphij return ACTION_IGNORE; 1397132451Sroberto} 139854359Sroberto 1399285612Sdelphij 1400182007Srobertostatic void 1401285612Sdelphijconvert_isc_if( 1402285612Sdelphij isc_interface_t *isc_if, 1403285612Sdelphij endpt *itf, 1404285612Sdelphij u_short port 1405285612Sdelphij ) 1406182007Sroberto{ 1407285612Sdelphij const u_char v6loop[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1408285612Sdelphij 0, 0, 0, 0, 0, 0, 0, 1}; 1409182007Sroberto 1410285612Sdelphij strlcpy(itf->name, isc_if->name, sizeof(itf->name)); 1411285612Sdelphij itf->ifindex = isc_if->ifindex; 1412285612Sdelphij itf->family = (u_short)isc_if->af; 1413285612Sdelphij AF(&itf->sin) = itf->family; 1414285612Sdelphij AF(&itf->mask) = itf->family; 1415285612Sdelphij AF(&itf->bcast) = itf->family; 1416285612Sdelphij SET_PORT(&itf->sin, port); 1417285612Sdelphij SET_PORT(&itf->mask, port); 1418285612Sdelphij SET_PORT(&itf->bcast, port); 141954359Sroberto 1420285612Sdelphij if (IS_IPV4(&itf->sin)) { 1421285612Sdelphij NSRCADR(&itf->sin) = isc_if->address.type.in.s_addr; 1422285612Sdelphij NSRCADR(&itf->mask) = isc_if->netmask.type.in.s_addr; 1423285612Sdelphij 1424285612Sdelphij if (isc_if->flags & INTERFACE_F_BROADCAST) { 1425132451Sroberto itf->flags |= INT_BROADCAST; 1426285612Sdelphij NSRCADR(&itf->bcast) = 1427285612Sdelphij isc_if->broadcast.type.in.s_addr; 1428132451Sroberto } 142954359Sroberto } 1430182007Sroberto#ifdef INCLUDE_IPV6_SUPPORT 1431285612Sdelphij else if (IS_IPV6(&itf->sin)) { 1432285612Sdelphij SET_ADDR6N(&itf->sin, isc_if->address.type.in6); 1433285612Sdelphij SET_ADDR6N(&itf->mask, isc_if->netmask.type.in6); 143454359Sroberto 1435285612Sdelphij SET_SCOPE(&itf->sin, isc_if->address.zone); 143654359Sroberto } 1437182007Sroberto#endif /* INCLUDE_IPV6_SUPPORT */ 143854359Sroberto 1439132451Sroberto 1440182007Sroberto /* Process the rest of the flags */ 1441182007Sroberto 1442285612Sdelphij itf->flags |= 1443285612Sdelphij ((INTERFACE_F_UP & isc_if->flags) 1444285612Sdelphij ? INT_UP : 0) 1445285612Sdelphij | ((INTERFACE_F_LOOPBACK & isc_if->flags) 1446285612Sdelphij ? INT_LOOPBACK : 0) 1447285612Sdelphij | ((INTERFACE_F_POINTTOPOINT & isc_if->flags) 1448285612Sdelphij ? INT_PPP : 0) 1449285612Sdelphij | ((INTERFACE_F_MULTICAST & isc_if->flags) 1450285612Sdelphij ? INT_MULTICAST : 0) 1451285612Sdelphij | ((INTERFACE_F_PRIVACY & isc_if->flags) 1452285612Sdelphij ? INT_PRIVACY : 0) 1453285612Sdelphij ; 1454182007Sroberto 1455285612Sdelphij /* 1456285612Sdelphij * Clear the loopback flag if the address is not localhost. 1457285612Sdelphij * http://bugs.ntp.org/1683 1458285612Sdelphij */ 1459285612Sdelphij if (INT_LOOPBACK & itf->flags) { 1460285612Sdelphij if (AF_INET == itf->family) { 1461285612Sdelphij if (127 != (SRCADR(&itf->sin) >> 24)) 1462285612Sdelphij itf->flags &= ~INT_LOOPBACK; 1463285612Sdelphij } else { 1464285612Sdelphij if (memcmp(v6loop, NSRCADR6(&itf->sin), 1465285612Sdelphij sizeof(NSRCADR6(&itf->sin)))) 1466285612Sdelphij itf->flags &= ~INT_LOOPBACK; 1467285612Sdelphij } 1468285612Sdelphij } 1469132451Sroberto} 1470182007Sroberto 1471285612Sdelphij 1472132451Sroberto/* 1473182007Sroberto * refresh_interface 1474182007Sroberto * 1475182007Sroberto * some OSes have been observed to keep 1476182007Sroberto * cached routes even when more specific routes 1477182007Sroberto * become available. 1478182007Sroberto * this can be mitigated by re-binding 1479182007Sroberto * the socket. 1480132451Sroberto */ 1481132451Srobertostatic int 1482285612Sdelphijrefresh_interface( 1483285612Sdelphij struct interface * interface 1484285612Sdelphij ) 1485182007Sroberto{ 1486182007Sroberto#ifdef OS_MISSES_SPECIFIC_ROUTE_UPDATES 1487285612Sdelphij if (interface->fd != INVALID_SOCKET) { 1488285612Sdelphij int bcast = (interface->flags & INT_BCASTXMIT) != 0; 1489285612Sdelphij /* as we forcibly close() the socket remove the 1490285612Sdelphij broadcast permission indication */ 1491285612Sdelphij if (bcast) 1492285612Sdelphij socket_broadcast_disable(interface, &interface->sin); 1493285612Sdelphij 1494182007Sroberto close_and_delete_fd_from_list(interface->fd); 1495285612Sdelphij 1496285612Sdelphij /* create new socket picking up a new first hop binding 1497285612Sdelphij at connect() time */ 1498182007Sroberto interface->fd = open_socket(&interface->sin, 1499285612Sdelphij bcast, 0, interface); 1500182007Sroberto /* 1501285612Sdelphij * reset TTL indication so TTL is is set again 1502182007Sroberto * next time around 1503182007Sroberto */ 1504182007Sroberto interface->last_ttl = 0; 1505285612Sdelphij return (interface->fd != INVALID_SOCKET); 1506285612Sdelphij } else 1507182007Sroberto return 0; /* invalid sockets are not refreshable */ 1508182007Sroberto#else /* !OS_MISSES_SPECIFIC_ROUTE_UPDATES */ 1509285612Sdelphij return (interface->fd != INVALID_SOCKET); 1510182007Sroberto#endif /* !OS_MISSES_SPECIFIC_ROUTE_UPDATES */ 1511182007Sroberto} 1512182007Sroberto 1513182007Sroberto/* 1514182007Sroberto * interface_update - externally callable update function 1515182007Sroberto */ 1516182007Srobertovoid 1517285612Sdelphijinterface_update( 1518285612Sdelphij interface_receiver_t receiver, 1519285612Sdelphij void * data) 1520182007Sroberto{ 1521285612Sdelphij int new_interface_found; 1522182007Sroberto 1523285612Sdelphij if (disable_dynamic_updates) 1524285612Sdelphij return; 1525182007Sroberto 1526285612Sdelphij BLOCKIO(); 1527285612Sdelphij new_interface_found = update_interfaces(NTP_PORT, receiver, data); 1528285612Sdelphij UNBLOCKIO(); 1529285612Sdelphij 1530285612Sdelphij if (!new_interface_found) 1531285612Sdelphij return; 1532285612Sdelphij 1533182007Sroberto#ifdef DEBUG 1534285612Sdelphij msyslog(LOG_DEBUG, "new interface(s) found: waking up resolver"); 1535182007Sroberto#endif 1536285612Sdelphij interrupt_worker_sleep(); 1537182007Sroberto} 1538182007Sroberto 1539285612Sdelphij 1540182007Sroberto/* 1541285612Sdelphij * sau_from_netaddr() - convert network address on-wire formats. 1542285612Sdelphij * Convert from libisc's isc_netaddr_t to NTP's sockaddr_u 1543182007Sroberto */ 1544285612Sdelphijvoid 1545285612Sdelphijsau_from_netaddr( 1546285612Sdelphij sockaddr_u *psau, 1547285612Sdelphij const isc_netaddr_t *pna 1548285612Sdelphij ) 1549285612Sdelphij{ 1550285612Sdelphij ZERO_SOCK(psau); 1551285612Sdelphij AF(psau) = (u_short)pna->family; 1552285612Sdelphij switch (pna->family) { 1553285612Sdelphij 1554285612Sdelphij case AF_INET: 1555285612Sdelphij memcpy(&psau->sa4.sin_addr, &pna->type.in, 1556285612Sdelphij sizeof(psau->sa4.sin_addr)); 1557285612Sdelphij break; 1558285612Sdelphij 1559285612Sdelphij case AF_INET6: 1560285612Sdelphij memcpy(&psau->sa6.sin6_addr, &pna->type.in6, 1561285612Sdelphij sizeof(psau->sa6.sin6_addr)); 1562285612Sdelphij break; 1563285612Sdelphij } 1564285612Sdelphij} 1565285612Sdelphij 1566285612Sdelphij 1567182007Srobertostatic int 1568285612Sdelphijis_wildcard_addr( 1569285612Sdelphij const sockaddr_u *psau 1570285612Sdelphij ) 1571182007Sroberto{ 1572285612Sdelphij if (IS_IPV4(psau) && !NSRCADR(psau)) 1573182007Sroberto return 1; 1574182007Sroberto 1575182007Sroberto#ifdef INCLUDE_IPV6_SUPPORT 1576285612Sdelphij if (IS_IPV6(psau) && S_ADDR6_EQ(psau, &in6addr_any)) 1577182007Sroberto return 1; 1578182007Sroberto#endif 1579182007Sroberto 1580182007Sroberto return 0; 1581182007Sroberto} 1582182007Sroberto 1583285612Sdelphij 1584182007Sroberto#ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND 1585182007Sroberto/* 1586182007Sroberto * enable/disable re-use of wildcard address socket 1587182007Sroberto */ 1588182007Srobertostatic void 1589285612Sdelphijset_wildcard_reuse( 1590285612Sdelphij u_short family, 1591285612Sdelphij int on 1592285612Sdelphij ) 1593182007Sroberto{ 1594285612Sdelphij struct interface *any; 1595182007Sroberto SOCKET fd = INVALID_SOCKET; 1596182007Sroberto 1597285612Sdelphij any = ANY_INTERFACE_BYFAM(family); 1598285612Sdelphij if (any != NULL) 1599285612Sdelphij fd = any->fd; 1600182007Sroberto 1601285612Sdelphij if (fd != INVALID_SOCKET) { 1602285612Sdelphij if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 1603330141Sdelphij (void *)&on, sizeof(on))) 1604285612Sdelphij msyslog(LOG_ERR, 1605285612Sdelphij "set_wildcard_reuse: setsockopt(SO_REUSEADDR, %s) failed: %m", 1606285612Sdelphij on ? "on" : "off"); 1607182007Sroberto 1608285612Sdelphij DPRINTF(4, ("set SO_REUSEADDR to %s on %s\n", 1609285612Sdelphij on ? "on" : "off", 1610285612Sdelphij stoa(&any->sin))); 1611182007Sroberto } 1612182007Sroberto} 1613182007Sroberto#endif /* OS_NEEDS_REUSEADDR_FOR_IFADDRBIND */ 1614182007Sroberto 1615338531Sdelphijstatic isc_boolean_t 1616338531Sdelphijcheck_flags( 1617338531Sdelphij sockaddr_u *psau, 1618338531Sdelphij const char *name, 1619338531Sdelphij u_int32 flags 1620338531Sdelphij ) 1621338531Sdelphij{ 1622338531Sdelphij#if defined(SIOCGIFAFLAG_IN) 1623338531Sdelphij struct ifreq ifr; 1624338531Sdelphij int fd; 1625285612Sdelphij 1626338531Sdelphij if (psau->sa.sa_family != AF_INET) 1627338531Sdelphij return ISC_FALSE; 1628338531Sdelphij if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 1629338531Sdelphij return ISC_FALSE; 1630338531Sdelphij ZERO(ifr); 1631338531Sdelphij memcpy(&ifr.ifr_addr, &psau->sa, sizeof(ifr.ifr_addr)); 1632338531Sdelphij strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1633338531Sdelphij if (ioctl(fd, SIOCGIFAFLAG_IN, &ifr) < 0) { 1634338531Sdelphij close(fd); 1635338531Sdelphij return ISC_FALSE; 1636338531Sdelphij } 1637338531Sdelphij close(fd); 1638338531Sdelphij if ((ifr.ifr_addrflags & flags) != 0) 1639338531Sdelphij return ISC_TRUE; 1640338531Sdelphij#endif /* SIOCGIFAFLAG_IN */ 1641338531Sdelphij return ISC_FALSE; 1642338531Sdelphij} 1643338531Sdelphij 1644199995Sumestatic isc_boolean_t 1645285612Sdelphijcheck_flags6( 1646285612Sdelphij sockaddr_u *psau, 1647285612Sdelphij const char *name, 1648285612Sdelphij u_int32 flags6 1649285612Sdelphij ) 1650199995Sume{ 1651289997Sglebius#if defined(INCLUDE_IPV6_SUPPORT) && defined(SIOCGIFAFLAG_IN6) 1652199995Sume struct in6_ifreq ifr6; 1653199995Sume int fd; 1654199995Sume 1655285612Sdelphij if (psau->sa.sa_family != AF_INET6) 1656199995Sume return ISC_FALSE; 1657199995Sume if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 1658199995Sume return ISC_FALSE; 1659285612Sdelphij ZERO(ifr6); 1660285612Sdelphij memcpy(&ifr6.ifr_addr, &psau->sa6, sizeof(ifr6.ifr_addr)); 1661285612Sdelphij strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 1662199995Sume if (ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) < 0) { 1663199995Sume close(fd); 1664199995Sume return ISC_FALSE; 1665199995Sume } 1666199995Sume close(fd); 1667289997Sglebius if ((ifr6.ifr_ifru.ifru_flags6 & flags6) != 0) 1668199995Sume return ISC_TRUE; 1669289997Sglebius#endif /* INCLUDE_IPV6_SUPPORT && SIOCGIFAFLAG_IN6 */ 1670199995Sume return ISC_FALSE; 1671199995Sume} 1672199995Sume 1673285612Sdelphijstatic isc_boolean_t 1674289997Sglebiusis_anycast( 1675285612Sdelphij sockaddr_u *psau, 1676285612Sdelphij const char *name 1677285612Sdelphij ) 1678285612Sdelphij{ 1679285612Sdelphij#ifdef IN6_IFF_ANYCAST 1680285612Sdelphij return check_flags6(psau, name, IN6_IFF_ANYCAST); 1681285612Sdelphij#else 1682285612Sdelphij return ISC_FALSE; 1683285612Sdelphij#endif 1684285612Sdelphij} 1685285612Sdelphij 1686285612Sdelphijstatic isc_boolean_t 1687285612Sdelphijis_valid( 1688285612Sdelphij sockaddr_u *psau, 1689285612Sdelphij const char *name 1690285612Sdelphij ) 1691285612Sdelphij{ 1692338531Sdelphij u_int32 flags; 1693285612Sdelphij 1694338531Sdelphij flags = 0; 1695338531Sdelphij switch (psau->sa.sa_family) { 1696338531Sdelphij case AF_INET: 1697338531Sdelphij#ifdef IN_IFF_DETACHED 1698338531Sdelphij flags |= IN_IFF_DETACHED; 1699338531Sdelphij#endif 1700338531Sdelphij#ifdef IN_IFF_TENTATIVE 1701338531Sdelphij flags |= IN_IFF_TENTATIVE; 1702338531Sdelphij#endif 1703338531Sdelphij return check_flags(psau, name, flags) ? ISC_FALSE : ISC_TRUE; 1704338531Sdelphij case AF_INET6: 1705285612Sdelphij#ifdef IN6_IFF_DEPARTED 1706338531Sdelphij flags |= IN6_IFF_DEPARTED; 1707285612Sdelphij#endif 1708285612Sdelphij#ifdef IN6_IFF_DETACHED 1709338531Sdelphij flags |= IN6_IFF_DETACHED; 1710285612Sdelphij#endif 1711285612Sdelphij#ifdef IN6_IFF_TENTATIVE 1712338531Sdelphij flags |= IN6_IFF_TENTATIVE; 1713285612Sdelphij#endif 1714338531Sdelphij return check_flags6(psau, name, flags) ? ISC_FALSE : ISC_TRUE; 1715338531Sdelphij default: 1716338531Sdelphij return ISC_FALSE; 1717338531Sdelphij } 1718285612Sdelphij} 1719285612Sdelphij 1720182007Sroberto/* 1721182007Sroberto * update_interface strategy 1722182007Sroberto * 1723182007Sroberto * toggle configuration phase 1724182007Sroberto * 1725182007Sroberto * Phase 1: 1726182007Sroberto * forall currently existing interfaces 1727182007Sroberto * if address is known: 1728285612Sdelphij * drop socket - rebind again 1729182007Sroberto * 1730182007Sroberto * if address is NOT known: 1731285612Sdelphij * attempt to create a new interface entry 1732182007Sroberto * 1733182007Sroberto * Phase 2: 1734182007Sroberto * forall currently known non MCAST and WILDCARD interfaces 1735182007Sroberto * if interface does not match configuration phase (not seen in phase 1): 1736285612Sdelphij * remove interface from known interface list 1737285612Sdelphij * forall peers associated with this interface 1738285612Sdelphij * disconnect peer from this interface 1739182007Sroberto * 1740182007Sroberto * Phase 3: 1741182007Sroberto * attempt to re-assign interfaces to peers 1742182007Sroberto * 1743182007Sroberto */ 1744182007Sroberto 1745182007Srobertostatic int 1746182007Srobertoupdate_interfaces( 1747285612Sdelphij u_short port, 1748285612Sdelphij interface_receiver_t receiver, 1749285612Sdelphij void * data 1750132451Sroberto ) 175154359Sroberto{ 1752285612Sdelphij isc_mem_t * mctx = (void *)-1; 1753285612Sdelphij interface_info_t ifi; 1754285612Sdelphij isc_interfaceiter_t * iter; 1755285612Sdelphij isc_result_t result; 1756285612Sdelphij isc_interface_t isc_if; 1757285612Sdelphij int new_interface_found; 1758285612Sdelphij unsigned int family; 1759285612Sdelphij endpt enumep; 1760285612Sdelphij endpt * ep; 1761285612Sdelphij endpt * next_ep; 176254359Sroberto 1763285612Sdelphij DPRINTF(3, ("update_interfaces(%d)\n", port)); 176454359Sroberto 1765182007Sroberto /* 1766182007Sroberto * phase one - scan interfaces 1767182007Sroberto * - create those that are not found 1768182007Sroberto * - update those that are found 1769182007Sroberto */ 1770132451Sroberto 1771285612Sdelphij new_interface_found = FALSE; 1772285612Sdelphij iter = NULL; 1773182007Sroberto result = isc_interfaceiter_create(mctx, &iter); 1774132451Sroberto 1775132451Sroberto if (result != ISC_R_SUCCESS) 1776182007Sroberto return 0; 1777132451Sroberto 1778285612Sdelphij /* 1779285612Sdelphij * Toggle system interface scan phase to find untouched 1780285612Sdelphij * interfaces to be deleted. 1781285612Sdelphij */ 1782285612Sdelphij sys_interphase ^= 0x1; 1783285612Sdelphij 1784132451Sroberto for (result = isc_interfaceiter_first(iter); 1785285612Sdelphij ISC_R_SUCCESS == result; 1786285612Sdelphij result = isc_interfaceiter_next(iter)) { 1787285612Sdelphij 1788182007Sroberto result = isc_interfaceiter_current(iter, &isc_if); 178954359Sroberto 1790132451Sroberto if (result != ISC_R_SUCCESS) 1791132451Sroberto break; 179254359Sroberto 1793132451Sroberto /* See if we have a valid family to use */ 1794132451Sroberto family = isc_if.address.family; 1795285612Sdelphij if (AF_INET != family && AF_INET6 != family) 179654359Sroberto continue; 1797285612Sdelphij if (AF_INET == family && !ipv4_works) 179854359Sroberto continue; 1799285612Sdelphij if (AF_INET6 == family && !ipv6_works) 180054359Sroberto continue; 180154359Sroberto 1802285612Sdelphij /* create prototype */ 1803285612Sdelphij init_interface(&enumep); 1804285612Sdelphij 1805285612Sdelphij convert_isc_if(&isc_if, &enumep, port); 1806285612Sdelphij 1807285612Sdelphij DPRINT_INTERFACE(4, (&enumep, "examining ", "\n")); 1808285612Sdelphij 1809182007Sroberto /* 1810285612Sdelphij * Check if and how we are going to use the interface. 1811182007Sroberto */ 1812285612Sdelphij switch (interface_action(enumep.name, &enumep.sin, 1813285612Sdelphij enumep.flags)) { 1814182007Sroberto 1815285612Sdelphij case ACTION_IGNORE: 1816285612Sdelphij DPRINTF(4, ("ignoring interface %s (%s) - by nic rules\n", 1817285612Sdelphij enumep.name, stoa(&enumep.sin))); 1818285612Sdelphij continue; 1819182007Sroberto 1820285612Sdelphij case ACTION_LISTEN: 1821285612Sdelphij DPRINTF(4, ("listen interface %s (%s) - by nic rules\n", 1822285612Sdelphij enumep.name, stoa(&enumep.sin))); 1823285612Sdelphij enumep.ignore_packets = ISC_FALSE; 1824285612Sdelphij break; 1825285612Sdelphij 1826285612Sdelphij case ACTION_DROP: 1827285612Sdelphij DPRINTF(4, ("drop on interface %s (%s) - by nic rules\n", 1828285612Sdelphij enumep.name, stoa(&enumep.sin))); 1829285612Sdelphij enumep.ignore_packets = ISC_TRUE; 1830285612Sdelphij break; 183154359Sroberto } 1832182007Sroberto 1833285612Sdelphij /* interfaces must be UP to be usable */ 1834285612Sdelphij if (!(enumep.flags & INT_UP)) { 1835285612Sdelphij DPRINTF(4, ("skipping interface %s (%s) - DOWN\n", 1836285612Sdelphij enumep.name, stoa(&enumep.sin))); 1837182007Sroberto continue; 1838182007Sroberto } 1839182007Sroberto 1840182007Sroberto /* 1841182007Sroberto * skip any interfaces UP and bound to a wildcard 1842182007Sroberto * address - some dhcp clients produce that in the 1843182007Sroberto * wild 1844182007Sroberto */ 1845285612Sdelphij if (is_wildcard_addr(&enumep.sin)) 1846182007Sroberto continue; 1847182007Sroberto 1848289997Sglebius if (is_anycast(&enumep.sin, isc_if.name)) 1849199995Sume continue; 1850199995Sume 1851182007Sroberto /* 1852285612Sdelphij * skip any address that is an invalid state to be used 1853182007Sroberto */ 1854285612Sdelphij if (!is_valid(&enumep.sin, isc_if.name)) 1855285612Sdelphij continue; 1856285612Sdelphij 1857285612Sdelphij /* 1858285612Sdelphij * map to local *address* in order to map all duplicate 1859285612Sdelphij * interfaces to an endpt structure with the appropriate 1860285612Sdelphij * socket. Our name space is (ip-address), NOT 1861285612Sdelphij * (interface name, ip-address). 1862285612Sdelphij */ 1863285612Sdelphij ep = getinterface(&enumep.sin, INT_WILDCARD); 1864285612Sdelphij 1865285612Sdelphij if (ep != NULL && refresh_interface(ep)) { 1866182007Sroberto /* 1867285612Sdelphij * found existing and up to date interface - 1868285612Sdelphij * mark present. 1869182007Sroberto */ 1870285612Sdelphij if (ep->phase != sys_interphase) { 1871285612Sdelphij /* 1872285612Sdelphij * On a new round we reset the name so 1873285612Sdelphij * the interface name shows up again if 1874285612Sdelphij * this address is no longer shared. 1875285612Sdelphij * We reset ignore_packets from the 1876285612Sdelphij * new prototype to respect any runtime 1877285612Sdelphij * changes to the nic rules. 1878285612Sdelphij */ 1879285612Sdelphij strlcpy(ep->name, enumep.name, 1880285612Sdelphij sizeof(ep->name)); 1881285612Sdelphij ep->ignore_packets = 1882285612Sdelphij enumep.ignore_packets; 1883285612Sdelphij } else { 1884285612Sdelphij /* name collision - rename interface */ 1885285612Sdelphij strlcpy(ep->name, "*multiple*", 1886285612Sdelphij sizeof(ep->name)); 1887285612Sdelphij } 1888182007Sroberto 1889285612Sdelphij DPRINT_INTERFACE(4, (ep, "updating ", 1890285612Sdelphij " present\n")); 1891285612Sdelphij 1892285612Sdelphij if (ep->ignore_packets != 1893285612Sdelphij enumep.ignore_packets) { 1894285612Sdelphij /* 1895285612Sdelphij * We have conflicting configurations 1896285612Sdelphij * for the interface address. This is 1897285612Sdelphij * caused by using -I <interfacename> 1898285612Sdelphij * for an interface that shares its 1899285612Sdelphij * address with other interfaces. We 1900285612Sdelphij * can not disambiguate incoming 1901285612Sdelphij * packets delivered to this socket 1902285612Sdelphij * without extra syscalls/features. 1903285612Sdelphij * These are not (commonly) available. 1904285612Sdelphij * Note this is a more unusual 1905285612Sdelphij * configuration where several 1906285612Sdelphij * interfaces share an address but 1907285612Sdelphij * filtering via interface name is 1908285612Sdelphij * attempted. We resolve the 1909285612Sdelphij * configuration conflict by disabling 1910285612Sdelphij * the processing of received packets. 1911285612Sdelphij * This leads to no service on the 1912285612Sdelphij * interface address where the conflict 1913285612Sdelphij * occurs. 1914285612Sdelphij */ 1915285612Sdelphij msyslog(LOG_ERR, 1916285612Sdelphij "WARNING: conflicting enable configuration for interfaces %s and %s for address %s - unsupported configuration - address DISABLED", 1917285612Sdelphij enumep.name, ep->name, 1918285612Sdelphij stoa(&enumep.sin)); 1919285612Sdelphij 1920285612Sdelphij ep->ignore_packets = ISC_TRUE; 1921285612Sdelphij } 1922285612Sdelphij 1923285612Sdelphij ep->phase = sys_interphase; 1924285612Sdelphij 1925182007Sroberto ifi.action = IFS_EXISTS; 1926285612Sdelphij ifi.ep = ep; 1927285612Sdelphij if (receiver != NULL) 1928285612Sdelphij (*receiver)(data, &ifi); 1929285612Sdelphij } else { 1930182007Sroberto /* 1931285612Sdelphij * This is new or refreshing failed - add to 1932285612Sdelphij * our interface list. If refreshing failed we 1933285612Sdelphij * will delete the interface structure in phase 1934285612Sdelphij * 2 as the interface was not marked current. 1935285612Sdelphij * We can bind to the address as the refresh 1936285612Sdelphij * code already closed the offending socket 1937182007Sroberto */ 1938285612Sdelphij ep = create_interface(port, &enumep); 1939182007Sroberto 1940285612Sdelphij if (ep != NULL) { 1941182007Sroberto ifi.action = IFS_CREATED; 1942285612Sdelphij ifi.ep = ep; 1943285612Sdelphij if (receiver != NULL) 1944285612Sdelphij (*receiver)(data, &ifi); 1945182007Sroberto 1946285612Sdelphij new_interface_found = TRUE; 1947285612Sdelphij DPRINT_INTERFACE(3, 1948285612Sdelphij (ep, "updating ", 1949285612Sdelphij " new - created\n")); 1950285612Sdelphij } else { 1951285612Sdelphij DPRINT_INTERFACE(3, 1952285612Sdelphij (&enumep, "updating ", 1953285612Sdelphij " new - creation FAILED")); 1954182007Sroberto 1955285612Sdelphij msyslog(LOG_INFO, 1956285612Sdelphij "failed to init interface for address %s", 1957285612Sdelphij stoa(&enumep.sin)); 1958182007Sroberto continue; 1959182007Sroberto } 1960182007Sroberto } 196154359Sroberto } 1962182007Sroberto 1963132451Sroberto isc_interfaceiter_destroy(&iter); 196454359Sroberto 1965132451Sroberto /* 1966285612Sdelphij * phase 2 - delete gone interfaces - reassigning peers to 1967285612Sdelphij * other interfaces 1968132451Sroberto */ 1969285612Sdelphij for (ep = ep_list; ep != NULL; ep = next_ep) { 1970285612Sdelphij next_ep = ep->elink; 1971182007Sroberto 1972285612Sdelphij /* 1973285612Sdelphij * if phase does not match sys_phase this interface was 1974285612Sdelphij * not enumerated during the last interface scan - so it 1975285612Sdelphij * is gone and will be deleted here unless it did not 1976285612Sdelphij * originate from interface enumeration (INT_WILDCARD, 1977285612Sdelphij * INT_MCASTIF). 1978285612Sdelphij */ 1979285612Sdelphij if (((INT_WILDCARD | INT_MCASTIF) & ep->flags) || 1980285612Sdelphij ep->phase == sys_interphase) 1981285612Sdelphij continue; 1982182007Sroberto 1983285612Sdelphij DPRINT_INTERFACE(3, (ep, "updating ", 1984285612Sdelphij "GONE - deleting\n")); 1985285612Sdelphij remove_interface(ep); 1986182007Sroberto 1987285612Sdelphij ifi.action = IFS_DELETED; 1988285612Sdelphij ifi.ep = ep; 1989285612Sdelphij if (receiver != NULL) 1990285612Sdelphij (*receiver)(data, &ifi); 1991182007Sroberto 1992285612Sdelphij /* disconnect peers from deleted endpt. */ 1993285612Sdelphij while (ep->peers != NULL) 1994285612Sdelphij set_peerdstadr(ep->peers, NULL); 1995182007Sroberto 1996285612Sdelphij /* 1997285612Sdelphij * update globals in case we lose 1998285612Sdelphij * a loopback interface 1999285612Sdelphij */ 2000285612Sdelphij if (ep == loopback_interface) 2001285612Sdelphij loopback_interface = NULL; 2002285612Sdelphij 2003285612Sdelphij delete_interface(ep); 2004285612Sdelphij } 2005285612Sdelphij 2006285612Sdelphij /* 2007285612Sdelphij * phase 3 - re-configure as the world has possibly changed 2008285612Sdelphij * 2009285612Sdelphij * never ever make this conditional again - it is needed to track 2010285612Sdelphij * routing updates. see bug #2506 2011285612Sdelphij */ 2012285612Sdelphij refresh_all_peerinterfaces(); 2013285612Sdelphij 2014285612Sdelphij if (broadcast_client_enabled) 2015285612Sdelphij io_setbclient(); 2016285612Sdelphij 2017285612Sdelphij if (sys_bclient) 2018285612Sdelphij io_setbclient(); 2019285612Sdelphij 2020289997Sglebius#ifdef MCAST 2021285612Sdelphij /* 2022285612Sdelphij * Check multicast interfaces and try to join multicast groups if 2023285612Sdelphij * not joined yet. 2024285612Sdelphij */ 2025285612Sdelphij for (ep = ep_list; ep != NULL; ep = ep->elink) { 2026285612Sdelphij remaddr_t *entry; 2027285612Sdelphij 2028285612Sdelphij if (!(INT_MCASTIF & ep->flags) || (INT_MCASTOPEN & ep->flags)) 2029285612Sdelphij continue; 2030285612Sdelphij 2031285612Sdelphij /* Find remote address that was linked to this interface */ 2032285612Sdelphij for (entry = remoteaddr_list; 2033285612Sdelphij entry != NULL; 2034285612Sdelphij entry = entry->link) { 2035285612Sdelphij if (entry->ep == ep) { 2036285612Sdelphij if (socket_multicast_enable(ep, &entry->addr)) { 2037285612Sdelphij msyslog(LOG_INFO, 2038285612Sdelphij "Joined %s socket to multicast group %s", 2039285612Sdelphij stoa(&ep->sin), 2040285612Sdelphij stoa(&entry->addr)); 2041182007Sroberto } 2042285612Sdelphij break; 2043182007Sroberto } 204454359Sroberto } 204554359Sroberto } 2046289997Sglebius#endif /* MCAST */ 204754359Sroberto 2048182007Sroberto return new_interface_found; 2049182007Sroberto} 205054359Sroberto 2051182007Sroberto 2052182007Sroberto/* 2053182007Sroberto * create_sockets - create a socket for each interface plus a default 2054182007Sroberto * socket for when we don't know where to send 2055182007Sroberto */ 2056182007Srobertostatic int 2057182007Srobertocreate_sockets( 2058182007Sroberto u_short port 2059182007Sroberto ) 2060182007Sroberto{ 2061182007Sroberto#ifndef HAVE_IO_COMPLETION_PORT 206254359Sroberto /* 2063182007Sroberto * I/O Completion Ports don't care about the select and FD_SET 206454359Sroberto */ 2065182007Sroberto maxactivefd = 0; 2066182007Sroberto FD_ZERO(&activefds); 2067182007Sroberto#endif 2068132451Sroberto 2069285612Sdelphij DPRINTF(2, ("create_sockets(%d)\n", port)); 2070132451Sroberto 2071182007Sroberto create_wildcards(port); 2072182007Sroberto 2073182007Sroberto update_interfaces(port, NULL, NULL); 2074285612Sdelphij 2075132451Sroberto /* 2076182007Sroberto * Now that we have opened all the sockets, turn off the reuse 2077182007Sroberto * flag for security. 2078132451Sroberto */ 2079182007Sroberto set_reuseaddr(0); 2080132451Sroberto 2081182007Sroberto DPRINTF(2, ("create_sockets: Total interfaces = %d\n", ninterfaces)); 2082132451Sroberto 208354359Sroberto return ninterfaces; 208454359Sroberto} 208554359Sroberto 208654359Sroberto/* 2087182007Sroberto * create_interface - create a new interface for a given prototype 2088182007Sroberto * binding the socket. 208954359Sroberto */ 2090182007Srobertostatic struct interface * 2091182007Srobertocreate_interface( 2092285612Sdelphij u_short port, 2093285612Sdelphij struct interface * protot 2094285612Sdelphij ) 209554359Sroberto{ 2096285612Sdelphij sockaddr_u resmask; 2097285612Sdelphij endpt * iface; 2098285612Sdelphij#if defined(MCAST) && defined(MULTICAST_NONEWSOCKET) 2099285612Sdelphij remaddr_t * entry; 2100285612Sdelphij remaddr_t * next_entry; 2101285612Sdelphij#endif 2102285612Sdelphij DPRINTF(2, ("create_interface(%s#%d)\n", stoa(&protot->sin), 2103285612Sdelphij port)); 210454359Sroberto 2105285612Sdelphij /* build an interface */ 2106285612Sdelphij iface = new_interface(protot); 2107132451Sroberto 2108182007Sroberto /* 2109182007Sroberto * create socket 2110182007Sroberto */ 2111285612Sdelphij iface->fd = open_socket(&iface->sin, 0, 0, iface); 211282498Sroberto 2113285612Sdelphij if (iface->fd != INVALID_SOCKET) 2114285612Sdelphij log_listen_address(iface); 211582498Sroberto 2116285612Sdelphij if ((INT_BROADCAST & iface->flags) 2117285612Sdelphij && iface->bfd != INVALID_SOCKET) 2118285612Sdelphij msyslog(LOG_INFO, "Listening on broadcast address %s#%d", 2119285612Sdelphij stoa((&iface->bcast)), port); 2120182007Sroberto 2121285612Sdelphij if (INVALID_SOCKET == iface->fd 2122285612Sdelphij && INVALID_SOCKET == iface->bfd) { 2123182007Sroberto msyslog(LOG_ERR, "unable to create socket on %s (%d) for %s#%d", 2124285612Sdelphij iface->name, 2125285612Sdelphij iface->ifnum, 2126285612Sdelphij stoa((&iface->sin)), 2127285612Sdelphij port); 2128285612Sdelphij delete_interface(iface); 2129182007Sroberto return NULL; 213054359Sroberto } 2131285612Sdelphij 2132285612Sdelphij /* 2133285612Sdelphij * Blacklist our own addresses, no use talking to ourself 2134182007Sroberto */ 2135285612Sdelphij SET_HOSTMASK(&resmask, AF(&iface->sin)); 2136285612Sdelphij hack_restrict(RESTRICT_FLAGS, &iface->sin, &resmask, 2137330141Sdelphij -4, RESM_NTPONLY | RESM_INTERFACE, RES_IGNORE, 0); 2138285612Sdelphij 2139182007Sroberto /* 2140182007Sroberto * set globals with the first found 2141182007Sroberto * loopback interface of the appropriate class 2142182007Sroberto */ 2143285612Sdelphij if (NULL == loopback_interface && AF_INET == iface->family 2144285612Sdelphij && (INT_LOOPBACK & iface->flags)) 2145285612Sdelphij loopback_interface = iface; 2146182007Sroberto 2147182007Sroberto /* 2148182007Sroberto * put into our interface list 2149182007Sroberto */ 2150285612Sdelphij add_addr_to_list(&iface->sin, iface); 2151285612Sdelphij add_interface(iface); 2152182007Sroberto 2153285612Sdelphij#if defined(MCAST) && defined(MULTICAST_NONEWSOCKET) 2154285612Sdelphij /* 2155285612Sdelphij * Join any previously-configured compatible multicast groups. 2156285612Sdelphij */ 2157285612Sdelphij if (INT_MULTICAST & iface->flags && 2158285612Sdelphij !((INT_LOOPBACK | INT_WILDCARD) & iface->flags) && 2159285612Sdelphij !iface->ignore_packets) { 2160285612Sdelphij for (entry = remoteaddr_list; 2161285612Sdelphij entry != NULL; 2162285612Sdelphij entry = next_entry) { 2163285612Sdelphij next_entry = entry->link; 2164285612Sdelphij if (AF(&iface->sin) != AF(&entry->addr) || 2165285612Sdelphij !IS_MCAST(&entry->addr)) 2166285612Sdelphij continue; 2167285612Sdelphij if (socket_multicast_enable(iface, 2168285612Sdelphij &entry->addr)) 2169285612Sdelphij msyslog(LOG_INFO, 2170285612Sdelphij "Joined %s socket to multicast group %s", 2171285612Sdelphij stoa(&iface->sin), 2172285612Sdelphij stoa(&entry->addr)); 2173285612Sdelphij else 2174285612Sdelphij msyslog(LOG_ERR, 2175285612Sdelphij "Failed to join %s socket to multicast group %s", 2176285612Sdelphij stoa(&iface->sin), 2177285612Sdelphij stoa(&entry->addr)); 2178285612Sdelphij } 2179285612Sdelphij } 2180285612Sdelphij#endif /* MCAST && MCAST_NONEWSOCKET */ 2181285612Sdelphij 2182285612Sdelphij DPRINT_INTERFACE(2, (iface, "created ", "\n")); 2183285612Sdelphij return iface; 218454359Sroberto} 218554359Sroberto 2186200576Sroberto 2187200576Sroberto#ifdef SO_EXCLUSIVEADDRUSE 2188200576Srobertostatic void 2189285612Sdelphijset_excladdruse( 2190285612Sdelphij SOCKET fd 2191285612Sdelphij ) 2192200576Sroberto{ 2193200576Sroberto int one = 1; 2194200576Sroberto int failed; 2195285612Sdelphij#ifdef SYS_WINNT 2196285612Sdelphij DWORD err; 2197285612Sdelphij#endif 2198200576Sroberto 2199200576Sroberto failed = setsockopt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 2200330141Sdelphij (void *)&one, sizeof(one)); 2201200576Sroberto 2202285612Sdelphij if (!failed) 2203285612Sdelphij return; 2204285612Sdelphij 2205285612Sdelphij#ifdef SYS_WINNT 2206285612Sdelphij /* 2207285612Sdelphij * Prior to Windows XP setting SO_EXCLUSIVEADDRUSE can fail with 2208285612Sdelphij * error WSAINVAL depending on service pack level and whether 2209285612Sdelphij * the user account is in the Administrators group. Do not 2210285612Sdelphij * complain if it fails that way on versions prior to XP (5.1). 2211285612Sdelphij */ 2212285612Sdelphij err = GetLastError(); 2213285612Sdelphij 2214285612Sdelphij if (isc_win32os_versioncheck(5, 1, 0, 0) < 0 /* < 5.1/XP */ 2215285612Sdelphij && WSAEINVAL == err) 2216285612Sdelphij return; 2217285612Sdelphij 2218285612Sdelphij SetLastError(err); 2219285612Sdelphij#endif 2220285612Sdelphij msyslog(LOG_ERR, 2221285612Sdelphij "setsockopt(%d, SO_EXCLUSIVEADDRUSE, on): %m", 2222285612Sdelphij (int)fd); 2223200576Sroberto} 2224200576Sroberto#endif /* SO_EXCLUSIVEADDRUSE */ 2225200576Sroberto 2226200576Sroberto 2227132451Sroberto/* 2228132451Sroberto * set_reuseaddr() - set/clear REUSEADDR on all sockets 2229132451Sroberto * NB possible hole - should we be doing this on broadcast 2230132451Sroberto * fd's also? 2231132451Sroberto */ 2232132451Srobertostatic void 2233285612Sdelphijset_reuseaddr( 2234285612Sdelphij int flag 2235285612Sdelphij ) 2236285612Sdelphij{ 2237200576Sroberto#ifndef SO_EXCLUSIVEADDRUSE 2238285612Sdelphij endpt *ep; 2239200576Sroberto 2240285612Sdelphij for (ep = ep_list; ep != NULL; ep = ep->elink) { 2241285612Sdelphij if (ep->flags & INT_WILDCARD) 2242285612Sdelphij continue; 2243200576Sroberto 2244132451Sroberto /* 2245285612Sdelphij * if ep->fd is INVALID_SOCKET, we might have a adapter 2246132451Sroberto * configured but not present 2247132451Sroberto */ 2248285612Sdelphij DPRINTF(4, ("setting SO_REUSEADDR on %.16s@%s to %s\n", 2249285612Sdelphij ep->name, stoa(&ep->sin), 2250285612Sdelphij flag ? "on" : "off")); 2251285612Sdelphij 2252285612Sdelphij if (ep->fd != INVALID_SOCKET) { 2253285612Sdelphij if (setsockopt(ep->fd, SOL_SOCKET, SO_REUSEADDR, 2254330141Sdelphij (void *)&flag, sizeof(flag))) { 2255285612Sdelphij msyslog(LOG_ERR, "set_reuseaddr: setsockopt(%s, SO_REUSEADDR, %s) failed: %m", 2256285612Sdelphij stoa(&ep->sin), flag ? "on" : "off"); 2257132451Sroberto } 2258132451Sroberto } 2259132451Sroberto } 2260200576Sroberto#endif /* ! SO_EXCLUSIVEADDRUSE */ 2261132451Sroberto} 2262132451Sroberto 2263182007Sroberto/* 2264182007Sroberto * This is just a wrapper around an internal function so we can 2265182007Sroberto * make other changes as necessary later on 2266182007Sroberto */ 2267182007Srobertovoid 2268285612Sdelphijenable_broadcast( 2269285612Sdelphij struct interface * iface, 2270285612Sdelphij sockaddr_u * baddr 2271285612Sdelphij ) 2272182007Sroberto{ 2273285612Sdelphij#ifdef OPEN_BCAST_SOCKET 2274182007Sroberto socket_broadcast_enable(iface, iface->fd, baddr); 2275182007Sroberto#endif 2276182007Sroberto} 2277132451Sroberto 2278285612Sdelphij#ifdef OPEN_BCAST_SOCKET 227954359Sroberto/* 2280182007Sroberto * Enable a broadcast address to a given socket 2281285612Sdelphij * The socket is in the ep_list all we need to do is enable 2282182007Sroberto * broadcasting. It is not this function's job to select the socket 228354359Sroberto */ 2284182007Srobertostatic isc_boolean_t 2285285612Sdelphijsocket_broadcast_enable( 2286285612Sdelphij struct interface * iface, 2287285612Sdelphij SOCKET fd, 2288285612Sdelphij sockaddr_u * baddr 2289285612Sdelphij ) 2290182007Sroberto{ 2291182007Sroberto#ifdef SO_BROADCAST 2292182007Sroberto int on = 1; 2293182007Sroberto 2294285612Sdelphij if (IS_IPV4(baddr)) { 2295182007Sroberto /* if this interface can support broadcast, set SO_BROADCAST */ 2296182007Sroberto if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, 2297330141Sdelphij (void *)&on, sizeof(on))) 2298285612Sdelphij msyslog(LOG_ERR, 2299285612Sdelphij "setsockopt(SO_BROADCAST) enable failure on address %s: %m", 2300285612Sdelphij stoa(baddr)); 2301285612Sdelphij else 2302285612Sdelphij DPRINTF(2, ("Broadcast enabled on socket %d for address %s\n", 2303285612Sdelphij fd, stoa(baddr))); 2304182007Sroberto } 2305285612Sdelphij iface->flags |= INT_BCASTXMIT; 2306182007Sroberto return ISC_TRUE; 2307182007Sroberto#else 2308182007Sroberto return ISC_FALSE; 2309182007Sroberto#endif /* SO_BROADCAST */ 2310182007Sroberto} 2311182007Sroberto 2312285612Sdelphij#ifdef OS_MISSES_SPECIFIC_ROUTE_UPDATES 2313182007Sroberto/* 2314182007Sroberto * Remove a broadcast address from a given socket 2315285612Sdelphij * The socket is in the ep_list all we need to do is disable 2316182007Sroberto * broadcasting. It is not this function's job to select the socket 2317182007Sroberto */ 2318182007Srobertostatic isc_boolean_t 2319285612Sdelphijsocket_broadcast_disable( 2320285612Sdelphij struct interface * iface, 2321285612Sdelphij sockaddr_u * baddr 2322285612Sdelphij ) 2323182007Sroberto{ 2324182007Sroberto#ifdef SO_BROADCAST 2325182007Sroberto int off = 0; /* This seems to be OK as an int */ 2326182007Sroberto 2327285612Sdelphij if (IS_IPV4(baddr) && setsockopt(iface->fd, SOL_SOCKET, 2328330141Sdelphij SO_BROADCAST, (void *)&off, sizeof(off))) 2329285612Sdelphij msyslog(LOG_ERR, 2330285612Sdelphij "setsockopt(SO_BROADCAST) disable failure on address %s: %m", 2331285612Sdelphij stoa(baddr)); 2332285612Sdelphij 2333285612Sdelphij iface->flags &= ~INT_BCASTXMIT; 2334182007Sroberto return ISC_TRUE; 2335182007Sroberto#else 2336182007Sroberto return ISC_FALSE; 2337182007Sroberto#endif /* SO_BROADCAST */ 2338182007Sroberto} 2339285612Sdelphij#endif /* OS_MISSES_SPECIFIC_ROUTE_UPDATES */ 2340182007Sroberto 2341182007Sroberto#endif /* OPEN_BCAST_SOCKET */ 2342285612Sdelphij 2343182007Sroberto/* 2344285612Sdelphij * return the broadcast client flag value 2345285612Sdelphij */ 2346285612Sdelphijisc_boolean_t 2347285612Sdelphijget_broadcastclient_flag(void) 2348285612Sdelphij{ 2349285612Sdelphij return (broadcast_client_enabled); 2350285612Sdelphij} 2351294569Sdelphij 2352285612Sdelphij/* 2353182007Sroberto * Check to see if the address is a multicast address 2354182007Sroberto */ 2355182007Srobertostatic isc_boolean_t 2356285612Sdelphijaddr_ismulticast( 2357285612Sdelphij sockaddr_u *maddr 2358285612Sdelphij ) 2359182007Sroberto{ 2360285612Sdelphij isc_boolean_t result; 2361182007Sroberto 2362285612Sdelphij#ifndef INCLUDE_IPV6_MULTICAST_SUPPORT 2363182007Sroberto /* 2364285612Sdelphij * If we don't have IPV6 support any IPV6 addr is not multicast 2365182007Sroberto */ 2366285612Sdelphij if (IS_IPV6(maddr)) 2367285612Sdelphij result = ISC_FALSE; 2368285612Sdelphij else 2369285612Sdelphij#endif 2370285612Sdelphij result = IS_MCAST(maddr); 2371285612Sdelphij 2372285612Sdelphij if (!result) 2373285612Sdelphij DPRINTF(4, ("address %s is not multicast\n", 2374285612Sdelphij stoa(maddr))); 2375285612Sdelphij 2376285612Sdelphij return result; 2377182007Sroberto} 2378182007Sroberto 2379182007Sroberto/* 2380182007Sroberto * Multicast servers need to set the appropriate Multicast interface 2381182007Sroberto * socket option in order for it to know which interface to use for 2382182007Sroberto * send the multicast packet. 2383182007Sroberto */ 238454359Srobertovoid 2385285612Sdelphijenable_multicast_if( 2386285612Sdelphij struct interface * iface, 2387285612Sdelphij sockaddr_u * maddr 2388285612Sdelphij ) 238954359Sroberto{ 239054359Sroberto#ifdef MCAST 2391222444Sbz#ifdef IP_MULTICAST_LOOP 2392285612Sdelphij TYPEOF_IP_MULTICAST_LOOP off = 0; 2393222444Sbz#endif 2394285612Sdelphij#if defined(INCLUDE_IPV6_MULTICAST_SUPPORT) && defined(IPV6_MULTICAST_LOOP) 2395285612Sdelphij u_int off6 = 0; 2396222444Sbz#endif 239754359Sroberto 2398289997Sglebius REQUIRE(AF(maddr) == AF(&iface->sin)); 2399285612Sdelphij 2400285612Sdelphij switch (AF(&iface->sin)) { 2401285612Sdelphij 2402182007Sroberto case AF_INET: 2403182007Sroberto#ifdef IP_MULTICAST_LOOP 2404182007Sroberto /* 2405285612Sdelphij * Don't send back to itself, but allow failure to set 2406182007Sroberto */ 2407285612Sdelphij if (setsockopt(iface->fd, IPPROTO_IP, 2408285612Sdelphij IP_MULTICAST_LOOP, 2409330141Sdelphij (void *)&off, 2410285612Sdelphij sizeof(off))) { 2411285612Sdelphij 2412285612Sdelphij msyslog(LOG_ERR, 2413285612Sdelphij "setsockopt IP_MULTICAST_LOOP failed: %m on socket %d, addr %s for multicast address %s", 2414285612Sdelphij iface->fd, stoa(&iface->sin), 2415285612Sdelphij stoa(maddr)); 2416132451Sroberto } 2417182007Sroberto#endif 2418182007Sroberto break; 2419132451Sroberto 2420182007Sroberto case AF_INET6: 2421182007Sroberto#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT 2422182007Sroberto#ifdef IPV6_MULTICAST_LOOP 2423132451Sroberto /* 2424285612Sdelphij * Don't send back to itself, but allow failure to set 2425182007Sroberto */ 2426285612Sdelphij if (setsockopt(iface->fd, IPPROTO_IPV6, 2427285612Sdelphij IPV6_MULTICAST_LOOP, 2428330141Sdelphij (void *) &off6, sizeof(off6))) { 2429285612Sdelphij 2430285612Sdelphij msyslog(LOG_ERR, 2431285612Sdelphij "setsockopt IPV6_MULTICAST_LOOP failed: %m on socket %d, addr %s for multicast address %s", 2432285612Sdelphij iface->fd, stoa(&iface->sin), 2433285612Sdelphij stoa(maddr)); 2434182007Sroberto } 2435132451Sroberto#endif 2436182007Sroberto break; 2437182007Sroberto#else 2438182007Sroberto return; 2439182007Sroberto#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ 2440182007Sroberto } 2441182007Sroberto return; 2442182007Sroberto#endif 2443182007Sroberto} 2444132451Sroberto 2445182007Sroberto/* 2446182007Sroberto * Add a multicast address to a given socket 2447285612Sdelphij * The socket is in the ep_list all we need to do is enable 2448182007Sroberto * multicasting. It is not this function's job to select the socket 2449182007Sroberto */ 2450285612Sdelphij#if defined(MCAST) 2451182007Srobertostatic isc_boolean_t 2452285612Sdelphijsocket_multicast_enable( 2453285612Sdelphij endpt * iface, 2454285612Sdelphij sockaddr_u * maddr 2455285612Sdelphij ) 2456182007Sroberto{ 2457285612Sdelphij struct ip_mreq mreq; 2458289997Sglebius# ifdef INCLUDE_IPV6_MULTICAST_SUPPORT 2459285612Sdelphij struct ipv6_mreq mreq6; 2460289997Sglebius# endif 2461285612Sdelphij switch (AF(maddr)) { 2462182007Sroberto 2463182007Sroberto case AF_INET: 2464285612Sdelphij ZERO(mreq); 2465285612Sdelphij mreq.imr_multiaddr = SOCK_ADDR4(maddr); 2466132451Sroberto mreq.imr_interface.s_addr = htonl(INADDR_ANY); 2467285612Sdelphij if (setsockopt(iface->fd, 2468285612Sdelphij IPPROTO_IP, 2469285612Sdelphij IP_ADD_MEMBERSHIP, 2470330141Sdelphij (void *)&mreq, 2471285612Sdelphij sizeof(mreq))) { 2472285612Sdelphij DPRINTF(2, ( 2473285612Sdelphij "setsockopt IP_ADD_MEMBERSHIP failed: %m on socket %d, addr %s for %x / %x (%s)", 2474285612Sdelphij iface->fd, stoa(&iface->sin), 2475285612Sdelphij mreq.imr_multiaddr.s_addr, 2476285612Sdelphij mreq.imr_interface.s_addr, 2477285612Sdelphij stoa(maddr))); 2478182007Sroberto return ISC_FALSE; 2479182007Sroberto } 2480182007Sroberto DPRINTF(4, ("Added IPv4 multicast membership on socket %d, addr %s for %x / %x (%s)\n", 2481182007Sroberto iface->fd, stoa(&iface->sin), 2482182007Sroberto mreq.imr_multiaddr.s_addr, 2483182007Sroberto mreq.imr_interface.s_addr, stoa(maddr))); 2484182007Sroberto break; 2485132451Sroberto 2486182007Sroberto case AF_INET6: 2487289997Sglebius# ifdef INCLUDE_IPV6_MULTICAST_SUPPORT 2488182007Sroberto /* 2489285612Sdelphij * Enable reception of multicast packets. 2490285612Sdelphij * If the address is link-local we can get the 2491285612Sdelphij * interface index from the scope id. Don't do this 2492285612Sdelphij * for other types of multicast addresses. For now let 2493285612Sdelphij * the kernel figure it out. 2494182007Sroberto */ 2495285612Sdelphij ZERO(mreq6); 2496285612Sdelphij mreq6.ipv6mr_multiaddr = SOCK_ADDR6(maddr); 2497285612Sdelphij mreq6.ipv6mr_interface = iface->ifindex; 2498182007Sroberto 2499285612Sdelphij if (setsockopt(iface->fd, IPPROTO_IPV6, 2500330141Sdelphij IPV6_JOIN_GROUP, (void *)&mreq6, 2501285612Sdelphij sizeof(mreq6))) { 2502285612Sdelphij DPRINTF(2, ( 2503285612Sdelphij "setsockopt IPV6_JOIN_GROUP failed: %m on socket %d, addr %s for interface %u (%s)", 2504285612Sdelphij iface->fd, stoa(&iface->sin), 2505285612Sdelphij mreq6.ipv6mr_interface, stoa(maddr))); 2506182007Sroberto return ISC_FALSE; 2507182007Sroberto } 2508285612Sdelphij DPRINTF(4, ("Added IPv6 multicast group on socket %d, addr %s for interface %u (%s)\n", 2509182007Sroberto iface->fd, stoa(&iface->sin), 2510182007Sroberto mreq6.ipv6mr_interface, stoa(maddr))); 2511289997Sglebius# else 2512182007Sroberto return ISC_FALSE; 2513289997Sglebius# endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ 2514182007Sroberto } 2515182007Sroberto iface->flags |= INT_MCASTOPEN; 2516182007Sroberto iface->num_mcast++; 2517285612Sdelphij 2518182007Sroberto return ISC_TRUE; 2519182007Sroberto} 2520285612Sdelphij#endif /* MCAST */ 252154359Sroberto 2522285612Sdelphij 2523182007Sroberto/* 2524182007Sroberto * Remove a multicast address from a given socket 2525285612Sdelphij * The socket is in the ep_list all we need to do is disable 2526182007Sroberto * multicasting. It is not this function's job to select the socket 2527182007Sroberto */ 2528285612Sdelphij#ifdef MCAST 2529182007Srobertostatic isc_boolean_t 2530285612Sdelphijsocket_multicast_disable( 2531285612Sdelphij struct interface * iface, 2532285612Sdelphij sockaddr_u * maddr 2533285612Sdelphij ) 2534182007Sroberto{ 2535289997Sglebius# ifdef INCLUDE_IPV6_MULTICAST_SUPPORT 2536182007Sroberto struct ipv6_mreq mreq6; 2537289997Sglebius# endif 2538182007Sroberto struct ip_mreq mreq; 2539182007Sroberto 2540285612Sdelphij ZERO(mreq); 2541285612Sdelphij 2542182007Sroberto if (find_addr_in_list(maddr) == NULL) { 2543285612Sdelphij DPRINTF(4, ("socket_multicast_disable(%s): not found\n", 2544285612Sdelphij stoa(maddr))); 2545182007Sroberto return ISC_TRUE; 2546182007Sroberto } 2547182007Sroberto 2548285612Sdelphij switch (AF(maddr)) { 2549285612Sdelphij 2550182007Sroberto case AF_INET: 2551285612Sdelphij mreq.imr_multiaddr = SOCK_ADDR4(maddr); 2552285612Sdelphij mreq.imr_interface = SOCK_ADDR4(&iface->sin); 2553285612Sdelphij if (setsockopt(iface->fd, IPPROTO_IP, 2554330141Sdelphij IP_DROP_MEMBERSHIP, (void *)&mreq, 2555285612Sdelphij sizeof(mreq))) { 2556285612Sdelphij 2557285612Sdelphij msyslog(LOG_ERR, 2558285612Sdelphij "setsockopt IP_DROP_MEMBERSHIP failed: %m on socket %d, addr %s for %x / %x (%s)", 2559285612Sdelphij iface->fd, stoa(&iface->sin), 2560285612Sdelphij SRCADR(maddr), SRCADR(&iface->sin), 2561285612Sdelphij stoa(maddr)); 2562182007Sroberto return ISC_FALSE; 2563132451Sroberto } 2564182007Sroberto break; 2565182007Sroberto case AF_INET6: 2566289997Sglebius# ifdef INCLUDE_IPV6_MULTICAST_SUPPORT 2567132451Sroberto /* 2568182007Sroberto * Disable reception of multicast packets 2569285612Sdelphij * If the address is link-local we can get the 2570285612Sdelphij * interface index from the scope id. Don't do this 2571285612Sdelphij * for other types of multicast addresses. For now let 2572285612Sdelphij * the kernel figure it out. 2573132451Sroberto */ 2574285612Sdelphij mreq6.ipv6mr_multiaddr = SOCK_ADDR6(maddr); 2575285612Sdelphij mreq6.ipv6mr_interface = iface->ifindex; 2576182007Sroberto 2577285612Sdelphij if (setsockopt(iface->fd, IPPROTO_IPV6, 2578330141Sdelphij IPV6_LEAVE_GROUP, (void *)&mreq6, 2579285612Sdelphij sizeof(mreq6))) { 2580285612Sdelphij 2581285612Sdelphij msyslog(LOG_ERR, 2582285612Sdelphij "setsockopt IPV6_LEAVE_GROUP failure: %m on socket %d, addr %s for %d (%s)", 2583285612Sdelphij iface->fd, stoa(&iface->sin), 2584285612Sdelphij iface->ifindex, stoa(maddr)); 2585182007Sroberto return ISC_FALSE; 2586132451Sroberto } 2587182007Sroberto break; 2588289997Sglebius# else 2589182007Sroberto return ISC_FALSE; 2590289997Sglebius# endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ 2591285612Sdelphij } 2592132451Sroberto 2593182007Sroberto iface->num_mcast--; 2594285612Sdelphij if (!iface->num_mcast) 2595182007Sroberto iface->flags &= ~INT_MCASTOPEN; 2596285612Sdelphij 2597182007Sroberto return ISC_TRUE; 2598182007Sroberto} 2599285612Sdelphij#endif /* MCAST */ 2600182007Sroberto 2601182007Sroberto/* 2602182007Sroberto * io_setbclient - open the broadcast client sockets 2603182007Sroberto */ 2604182007Srobertovoid 2605182007Srobertoio_setbclient(void) 2606182007Sroberto{ 2607285612Sdelphij#ifdef OPEN_BCAST_SOCKET 2608285612Sdelphij struct interface * interf; 2609316069Sdelphij unsigned int nif; 2610182007Sroberto 2611285612Sdelphij nif = 0; 2612182007Sroberto set_reuseaddr(1); 2613182007Sroberto 2614285612Sdelphij for (interf = ep_list; 2615182007Sroberto interf != NULL; 2616285612Sdelphij interf = interf->elink) { 2617285612Sdelphij 2618285612Sdelphij if (interf->flags & (INT_WILDCARD | INT_LOOPBACK)) 2619285612Sdelphij continue; 2620285612Sdelphij 2621182007Sroberto /* use only allowed addresses */ 2622285612Sdelphij if (interf->ignore_packets) 2623182007Sroberto continue; 2624182007Sroberto 2625285612Sdelphij /* Need a broadcast-capable interface */ 2626182007Sroberto if (!(interf->flags & INT_BROADCAST)) 2627182007Sroberto continue; 2628182007Sroberto 2629285612Sdelphij /* Only IPv4 addresses are valid for broadcast */ 2630298699Sdelphij REQUIRE(IS_IPV4(&interf->bcast)); 2631182007Sroberto 2632182007Sroberto /* Do we already have the broadcast address open? */ 2633182007Sroberto if (interf->flags & INT_BCASTOPEN) { 2634285612Sdelphij /* 2635285612Sdelphij * account for already open interfaces to avoid 2636285612Sdelphij * misleading warning below 2637285612Sdelphij */ 2638182007Sroberto nif++; 2639182007Sroberto continue; 2640182007Sroberto } 2641182007Sroberto 2642132451Sroberto /* 2643182007Sroberto * Try to open the broadcast address 2644132451Sroberto */ 2645182007Sroberto interf->family = AF_INET; 2646285612Sdelphij interf->bfd = open_socket(&interf->bcast, 1, 0, interf); 2647132451Sroberto 2648285612Sdelphij /* 2649285612Sdelphij * If we succeeded then we use it otherwise enable 2650285612Sdelphij * broadcast on the interface address 2651182007Sroberto */ 2652285612Sdelphij if (interf->bfd != INVALID_SOCKET) { 2653182007Sroberto nif++; 2654285612Sdelphij interf->flags |= INT_BCASTOPEN; 2655285612Sdelphij msyslog(LOG_INFO, 2656285612Sdelphij "Listen for broadcasts to %s on interface #%d %s", 2657285612Sdelphij stoa(&interf->bcast), interf->ifnum, interf->name); 2658298699Sdelphij } else switch (errno) { 2659298699Sdelphij /* Silently ignore EADDRINUSE as we probably 2660298699Sdelphij * opened the socket already for an address in 2661298699Sdelphij * the same network */ 2662298699Sdelphij case EADDRINUSE: 2663298699Sdelphij /* Some systems cannot bind a socket to a broadcast 2664298699Sdelphij * address, as that is not a valid host address. */ 2665298699Sdelphij case EADDRNOTAVAIL: 2666298699Sdelphij# ifdef SYS_WINNT /*TODO: use for other systems, too? */ 2667298699Sdelphij /* avoid recurrence here -- if we already have a 2668298699Sdelphij * regular socket, it's quite useless to try this 2669298699Sdelphij * again. 2670298699Sdelphij */ 2671298699Sdelphij if (interf->fd != INVALID_SOCKET) { 2672298699Sdelphij interf->flags |= INT_BCASTOPEN; 2673298699Sdelphij nif++; 2674298699Sdelphij } 2675298699Sdelphij# endif 2676298699Sdelphij break; 2677298699Sdelphij 2678298699Sdelphij default: 2679298699Sdelphij msyslog(LOG_INFO, 2680298699Sdelphij "failed to listen for broadcasts to %s on interface #%d %s", 2681298699Sdelphij stoa(&interf->bcast), interf->ifnum, interf->name); 2682298699Sdelphij break; 2683182007Sroberto } 268454359Sroberto } 2685182007Sroberto set_reuseaddr(0); 2686316069Sdelphij if (nif != 0) { 2687285612Sdelphij broadcast_client_enabled = ISC_TRUE; 2688285612Sdelphij DPRINTF(1, ("io_setbclient: listening to %d broadcast addresses\n", nif)); 2689316069Sdelphij } else { 2690285612Sdelphij broadcast_client_enabled = ISC_FALSE; 2691285612Sdelphij msyslog(LOG_ERR, 2692285612Sdelphij "Unable to listen for broadcasts, no broadcast interfaces available"); 2693285612Sdelphij } 2694182007Sroberto#else 2695285612Sdelphij msyslog(LOG_ERR, 2696285612Sdelphij "io_setbclient: Broadcast Client disabled by build"); 2697285612Sdelphij#endif /* OPEN_BCAST_SOCKET */ 269854359Sroberto} 269954359Sroberto 270054359Sroberto/* 270154359Sroberto * io_unsetbclient - close the broadcast client sockets 270254359Sroberto */ 270354359Srobertovoid 270454359Srobertoio_unsetbclient(void) 270554359Sroberto{ 2706285612Sdelphij endpt *ep; 270754359Sroberto 2708285612Sdelphij for (ep = ep_list; ep != NULL; ep = ep->elink) { 2709285612Sdelphij if (INT_WILDCARD & ep->flags) 2710285612Sdelphij continue; 2711285612Sdelphij if (!(INT_BCASTOPEN & ep->flags)) 2712285612Sdelphij continue; 2713285612Sdelphij 2714285612Sdelphij if (ep->bfd != INVALID_SOCKET) { 2715285612Sdelphij /* destroy broadcast listening socket */ 2716285612Sdelphij msyslog(LOG_INFO, 2717285612Sdelphij "stop listening for broadcasts to %s on interface #%d %s", 2718285612Sdelphij stoa(&ep->bcast), ep->ifnum, ep->name); 2719298699Sdelphij# ifdef HAVE_IO_COMPLETION_PORT 2720298699Sdelphij io_completion_port_remove_socket(ep->bfd, ep); 2721298699Sdelphij# endif 2722285612Sdelphij close_and_delete_fd_from_list(ep->bfd); 2723285612Sdelphij ep->bfd = INVALID_SOCKET; 2724285612Sdelphij } 2725298699Sdelphij ep->flags &= ~INT_BCASTOPEN; 272654359Sroberto } 2727285612Sdelphij broadcast_client_enabled = ISC_FALSE; 272854359Sroberto} 272954359Sroberto 2730182007Sroberto/* 2731182007Sroberto * io_multicast_add() - add multicast group address 2732182007Sroberto */ 2733182007Srobertovoid 2734182007Srobertoio_multicast_add( 2735285612Sdelphij sockaddr_u *addr 2736182007Sroberto ) 2737182007Sroberto{ 2738182007Sroberto#ifdef MCAST 2739285612Sdelphij endpt * ep; 2740285612Sdelphij endpt * one_ep; 2741285612Sdelphij 2742182007Sroberto /* 2743182007Sroberto * Check to see if this is a multicast address 2744182007Sroberto */ 2745285612Sdelphij if (!addr_ismulticast(addr)) 2746182007Sroberto return; 274754359Sroberto 2748182007Sroberto /* If we already have it we can just return */ 2749285612Sdelphij if (NULL != find_flagged_addr_in_list(addr, INT_MCASTOPEN)) { 2750285612Sdelphij msyslog(LOG_INFO, 2751285612Sdelphij "Duplicate request found for multicast address %s", 2752285612Sdelphij stoa(addr)); 2753182007Sroberto return; 2754182007Sroberto } 2755182007Sroberto 2756289997Sglebius# ifndef MULTICAST_NONEWSOCKET 2757285612Sdelphij ep = new_interface(NULL); 2758285612Sdelphij 2759182007Sroberto /* 2760182007Sroberto * Open a new socket for the multicast address 2761182007Sroberto */ 2762285612Sdelphij ep->sin = *addr; 2763285612Sdelphij SET_PORT(&ep->sin, NTP_PORT); 2764285612Sdelphij ep->family = AF(&ep->sin); 2765285612Sdelphij AF(&ep->mask) = ep->family; 2766285612Sdelphij SET_ONESMASK(&ep->mask); 2767182007Sroberto 2768182007Sroberto set_reuseaddr(1); 2769285612Sdelphij ep->bfd = INVALID_SOCKET; 2770285612Sdelphij ep->fd = open_socket(&ep->sin, 0, 0, ep); 2771285612Sdelphij if (ep->fd != INVALID_SOCKET) { 2772285612Sdelphij ep->ignore_packets = ISC_FALSE; 2773285612Sdelphij ep->flags |= INT_MCASTIF; 2774330141Sdelphij ep->ifindex = SCOPE(addr); 2775182007Sroberto 2776285612Sdelphij strlcpy(ep->name, "multicast", sizeof(ep->name)); 2777285612Sdelphij DPRINT_INTERFACE(2, (ep, "multicast add ", "\n")); 2778285612Sdelphij add_interface(ep); 2779285612Sdelphij log_listen_address(ep); 2780285612Sdelphij } else { 2781285612Sdelphij /* bind failed, re-use wildcard interface */ 2782285612Sdelphij delete_interface(ep); 2783182007Sroberto 2784285612Sdelphij if (IS_IPV4(addr)) 2785285612Sdelphij ep = wildipv4; 2786285612Sdelphij else if (IS_IPV6(addr)) 2787285612Sdelphij ep = wildipv6; 2788285612Sdelphij else 2789285612Sdelphij ep = NULL; 2790285612Sdelphij 2791285612Sdelphij if (ep != NULL) { 2792182007Sroberto /* HACK ! -- stuff in an address */ 2793285612Sdelphij /* because we don't bind addr? DH */ 2794285612Sdelphij ep->bcast = *addr; 2795285612Sdelphij msyslog(LOG_ERR, 2796285612Sdelphij "multicast address %s using wildcard interface #%d %s", 2797285612Sdelphij stoa(addr), ep->ifnum, ep->name); 2798182007Sroberto } else { 2799285612Sdelphij msyslog(LOG_ERR, 2800285612Sdelphij "No multicast socket available to use for address %s", 2801285612Sdelphij stoa(addr)); 2802182007Sroberto return; 2803182007Sroberto } 2804182007Sroberto } 2805285612Sdelphij { /* in place of the { following for in #else clause */ 2806285612Sdelphij one_ep = ep; 2807289997Sglebius# else /* MULTICAST_NONEWSOCKET follows */ 2808182007Sroberto /* 2809285612Sdelphij * For the case where we can't use a separate socket (Windows) 2810285612Sdelphij * join each applicable endpoint socket to the group address. 2811182007Sroberto */ 2812285612Sdelphij if (IS_IPV4(addr)) 2813285612Sdelphij one_ep = wildipv4; 2814285612Sdelphij else 2815285612Sdelphij one_ep = wildipv6; 2816285612Sdelphij for (ep = ep_list; ep != NULL; ep = ep->elink) { 2817285612Sdelphij if (ep->ignore_packets || AF(&ep->sin) != AF(addr) || 2818285612Sdelphij !(INT_MULTICAST & ep->flags) || 2819285612Sdelphij (INT_LOOPBACK | INT_WILDCARD) & ep->flags) 2820285612Sdelphij continue; 2821285612Sdelphij one_ep = ep; 2822289997Sglebius# endif /* MULTICAST_NONEWSOCKET */ 2823285612Sdelphij if (socket_multicast_enable(ep, addr)) 2824285612Sdelphij msyslog(LOG_INFO, 2825285612Sdelphij "Joined %s socket to multicast group %s", 2826285612Sdelphij stoa(&ep->sin), 2827285612Sdelphij stoa(addr)); 2828182007Sroberto } 2829182007Sroberto 2830285612Sdelphij add_addr_to_list(addr, one_ep); 2831285612Sdelphij#else /* !MCAST follows*/ 2832285612Sdelphij msyslog(LOG_ERR, 2833285612Sdelphij "Can not add multicast address %s: no multicast support", 2834285612Sdelphij stoa(addr)); 2835182007Sroberto#endif 2836182007Sroberto return; 2837182007Sroberto} 2838182007Sroberto 2839285612Sdelphij 284054359Sroberto/* 284154359Sroberto * io_multicast_del() - delete multicast group address 284254359Sroberto */ 284354359Srobertovoid 284454359Srobertoio_multicast_del( 2845285612Sdelphij sockaddr_u * addr 284654359Sroberto ) 284754359Sroberto{ 284854359Sroberto#ifdef MCAST 2849285612Sdelphij endpt *iface; 285054359Sroberto 2851182007Sroberto /* 2852182007Sroberto * Check to see if this is a multicast address 2853182007Sroberto */ 2854285612Sdelphij if (!addr_ismulticast(addr)) { 2855285612Sdelphij msyslog(LOG_ERR, "invalid multicast address %s", 2856285612Sdelphij stoa(addr)); 2857182007Sroberto return; 2858182007Sroberto } 2859132451Sroberto 2860285612Sdelphij /* 2861285612Sdelphij * Disable reception of multicast packets 2862285612Sdelphij */ 2863285612Sdelphij while ((iface = find_flagged_addr_in_list(addr, INT_MCASTOPEN)) 2864285612Sdelphij != NULL) 2865285612Sdelphij socket_multicast_disable(iface, addr); 2866132451Sroberto 2867285612Sdelphij delete_addr_from_list(addr); 2868182007Sroberto 286954359Sroberto#else /* not MCAST */ 2870285612Sdelphij msyslog(LOG_ERR, 2871285612Sdelphij "Can not delete multicast address %s: no multicast support", 2872285612Sdelphij stoa(addr)); 287354359Sroberto#endif /* not MCAST */ 287454359Sroberto} 287554359Sroberto 287654359Sroberto 287754359Sroberto/* 287854359Sroberto * open_socket - open a socket, returning the file descriptor 287954359Sroberto */ 2880132451Sroberto 2881132451Srobertostatic SOCKET 288254359Srobertoopen_socket( 2883285612Sdelphij sockaddr_u * addr, 2884285612Sdelphij int bcast, 2885285612Sdelphij int turn_off_reuse, 2886285612Sdelphij endpt * interf 288754359Sroberto ) 288854359Sroberto{ 2889285612Sdelphij SOCKET fd; 2890285612Sdelphij int errval; 2891200576Sroberto /* 2892285612Sdelphij * int is OK for REUSEADR per 2893200576Sroberto * http://www.kohala.com/start/mcast.api.txt 2894200576Sroberto */ 2895285612Sdelphij int on = 1; 2896285612Sdelphij int off = 0; 2897200576Sroberto 2898285612Sdelphij if (IS_IPV6(addr) && !ipv6_works) 2899285612Sdelphij return INVALID_SOCKET; 290054359Sroberto 290154359Sroberto /* create a datagram (UDP) socket */ 2902285612Sdelphij fd = socket(AF(addr), SOCK_DGRAM, 0); 2903200576Sroberto if (INVALID_SOCKET == fd) { 2904285612Sdelphij errval = socket_errno(); 2905285612Sdelphij msyslog(LOG_ERR, 2906285612Sdelphij "socket(AF_INET%s, SOCK_DGRAM, 0) failed on address %s: %m", 2907285612Sdelphij IS_IPV6(addr) ? "6" : "", stoa(addr)); 2908200576Sroberto 2909285612Sdelphij if (errval == EPROTONOSUPPORT || 2910200576Sroberto errval == EAFNOSUPPORT || 2911132451Sroberto errval == EPFNOSUPPORT) 2912132451Sroberto return (INVALID_SOCKET); 2913285612Sdelphij 2914285612Sdelphij errno = errval; 2915285612Sdelphij msyslog(LOG_ERR, 2916285612Sdelphij "unexpected socket() error %m code %d (not EPROTONOSUPPORT nor EAFNOSUPPORT nor EPFNOSUPPORT) - exiting", 2917285612Sdelphij errno); 291854359Sroberto exit(1); 291954359Sroberto } 2920200576Sroberto 2921182007Sroberto#ifdef SYS_WINNT 2922200576Sroberto connection_reset_fix(fd, addr); 2923200576Sroberto#endif 2924182007Sroberto /* 2925182007Sroberto * Fixup the file descriptor for some systems 2926182007Sroberto * See bug #530 for details of the issue. 2927182007Sroberto */ 2928182007Sroberto fd = move_fd(fd); 2929182007Sroberto 2930182007Sroberto /* 2931182007Sroberto * set SO_REUSEADDR since we will be binding the same port 2932200576Sroberto * number on each interface according to turn_off_reuse. 2933200576Sroberto * This is undesirable on Windows versions starting with 2934200576Sroberto * Windows XP (numeric version 5.1). 2935182007Sroberto */ 2936200576Sroberto#ifdef SYS_WINNT 2937200576Sroberto if (isc_win32os_versioncheck(5, 1, 0, 0) < 0) /* before 5.1 */ 2938200576Sroberto#endif 2939200576Sroberto if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 2940330141Sdelphij (void *)((turn_off_reuse) 2941285612Sdelphij ? &off 2942285612Sdelphij : &on), 2943200576Sroberto sizeof(on))) { 2944182007Sroberto 2945285612Sdelphij msyslog(LOG_ERR, 2946285612Sdelphij "setsockopt SO_REUSEADDR %s fails for address %s: %m", 2947285612Sdelphij (turn_off_reuse) 2948285612Sdelphij ? "off" 2949285612Sdelphij : "on", 2950285612Sdelphij stoa(addr)); 2951200576Sroberto closesocket(fd); 2952200576Sroberto return INVALID_SOCKET; 2953200576Sroberto } 2954200576Sroberto#ifdef SO_EXCLUSIVEADDRUSE 2955200576Sroberto /* 2956200576Sroberto * setting SO_EXCLUSIVEADDRUSE on the wildcard we open 2957200576Sroberto * first will cause more specific binds to fail. 2958200576Sroberto */ 2959200576Sroberto if (!(interf->flags & INT_WILDCARD)) 2960200576Sroberto set_excladdruse(fd); 2961200576Sroberto#endif 2962182007Sroberto 2963182007Sroberto /* 2964182007Sroberto * IPv4 specific options go here 2965182007Sroberto */ 2966285612Sdelphij if (IS_IPV4(addr)) { 2967285612Sdelphij#if defined(IPPROTO_IP) && defined(IP_TOS) 2968330141Sdelphij if (setsockopt(fd, IPPROTO_IP, IP_TOS, (void *)&qos, 2969285612Sdelphij sizeof(qos))) 2970285612Sdelphij msyslog(LOG_ERR, 2971285612Sdelphij "setsockopt IP_TOS (%02x) fails on address %s: %m", 2972285612Sdelphij qos, stoa(addr)); 2973285612Sdelphij#endif /* IPPROTO_IP && IP_TOS */ 2974285612Sdelphij if (bcast) 2975285612Sdelphij socket_broadcast_enable(interf, fd, addr); 2976182007Sroberto } 2977132451Sroberto 2978182007Sroberto /* 2979182007Sroberto * IPv6 specific options go here 2980182007Sroberto */ 2981285612Sdelphij if (IS_IPV6(addr)) { 2982285612Sdelphij#if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS) 2983330141Sdelphij if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, (void *)&qos, 2984285612Sdelphij sizeof(qos))) 2985285612Sdelphij msyslog(LOG_ERR, 2986285612Sdelphij "setsockopt IPV6_TCLASS (%02x) fails on address %s: %m", 2987285612Sdelphij qos, stoa(addr)); 2988285612Sdelphij#endif /* IPPROTO_IPV6 && IPV6_TCLASS */ 2989285612Sdelphij#ifdef IPV6_V6ONLY 2990285612Sdelphij if (isc_net_probe_ipv6only() == ISC_R_SUCCESS 2991285612Sdelphij && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, 2992330141Sdelphij (void *)&on, sizeof(on))) 2993285612Sdelphij msyslog(LOG_ERR, 2994285612Sdelphij "setsockopt IPV6_V6ONLY on fails on address %s: %m", 2995132451Sroberto stoa(addr)); 2996285612Sdelphij#endif 2997285612Sdelphij#ifdef IPV6_BINDV6ONLY 2998285612Sdelphij if (setsockopt(fd, IPPROTO_IPV6, IPV6_BINDV6ONLY, 2999330141Sdelphij (void *)&on, sizeof(on))) 3000285612Sdelphij msyslog(LOG_ERR, 3001285612Sdelphij "setsockopt IPV6_BINDV6ONLY on fails on address %s: %m", 3002285612Sdelphij stoa(addr)); 3003285612Sdelphij#endif 3004182007Sroberto } 3005132451Sroberto 3006182007Sroberto#ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND 3007182007Sroberto /* 3008182007Sroberto * some OSes don't allow binding to more specific 3009182007Sroberto * addresses if a wildcard address already bound 3010182007Sroberto * to the port and SO_REUSEADDR is not set 3011182007Sroberto */ 3012285612Sdelphij if (!is_wildcard_addr(addr)) 3013285612Sdelphij set_wildcard_reuse(AF(addr), 1); 3014182007Sroberto#endif 301556746Sroberto 301654359Sroberto /* 301754359Sroberto * bind the local address. 301854359Sroberto */ 3019285612Sdelphij errval = bind(fd, &addr->sa, SOCKLEN(addr)); 3020132451Sroberto 3021182007Sroberto#ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND 3022285612Sdelphij if (!is_wildcard_addr(addr)) 3023285612Sdelphij set_wildcard_reuse(AF(addr), 0); 3024182007Sroberto#endif 3025132451Sroberto 3026182007Sroberto if (errval < 0) { 302754359Sroberto /* 3028182007Sroberto * Don't log this under all conditions 302954359Sroberto */ 3030182007Sroberto if (turn_off_reuse == 0 3031182007Sroberto#ifdef DEBUG 3032182007Sroberto || debug > 1 3033182007Sroberto#endif 3034285612Sdelphij ) { 3035285612Sdelphij msyslog(LOG_ERR, 3036285612Sdelphij "bind(%d) AF_INET%s %s#%d%s flags 0x%x failed: %m", 3037285612Sdelphij fd, IS_IPV6(addr) ? "6" : "", 3038285612Sdelphij stoa(addr), SRCPORT(addr), 3039285612Sdelphij IS_MCAST(addr) ? " (multicast)" : "", 3040285612Sdelphij interf->flags); 3041132451Sroberto } 3042182007Sroberto 3043182007Sroberto closesocket(fd); 3044285612Sdelphij 3045132451Sroberto return INVALID_SOCKET; 304654359Sroberto } 3047182007Sroberto 3048182007Sroberto#ifdef HAVE_TIMESTAMP 3049182007Sroberto { 3050182007Sroberto if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, 3051330141Sdelphij (void *)&on, sizeof(on))) 3052285612Sdelphij msyslog(LOG_DEBUG, 3053285612Sdelphij "setsockopt SO_TIMESTAMP on fails on address %s: %m", 3054285612Sdelphij stoa(addr)); 3055182007Sroberto else 3056285612Sdelphij DPRINTF(4, ("setsockopt SO_TIMESTAMP enabled on fd %d address %s\n", 3057285612Sdelphij fd, stoa(addr))); 3058285612Sdelphij } 3059182007Sroberto#endif 3060285612Sdelphij#ifdef HAVE_TIMESTAMPNS 3061285612Sdelphij { 3062285612Sdelphij if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPNS, 3063330141Sdelphij (void *)&on, sizeof(on))) 3064285612Sdelphij msyslog(LOG_DEBUG, 3065285612Sdelphij "setsockopt SO_TIMESTAMPNS on fails on address %s: %m", 3066285612Sdelphij stoa(addr)); 3067285612Sdelphij else 3068285612Sdelphij DPRINTF(4, ("setsockopt SO_TIMESTAMPNS enabled on fd %d address %s\n", 3069285612Sdelphij fd, stoa(addr))); 3070285612Sdelphij } 3071182007Sroberto#endif 3072285612Sdelphij#ifdef HAVE_BINTIME 3073285612Sdelphij { 3074285612Sdelphij if (setsockopt(fd, SOL_SOCKET, SO_BINTIME, 3075330141Sdelphij (void *)&on, sizeof(on))) 3076285612Sdelphij msyslog(LOG_DEBUG, 3077285612Sdelphij "setsockopt SO_BINTIME on fails on address %s: %m", 3078285612Sdelphij stoa(addr)); 3079285612Sdelphij else 3080285612Sdelphij DPRINTF(4, ("setsockopt SO_BINTIME enabled on fd %d address %s\n", 3081285612Sdelphij fd, stoa(addr))); 3082285612Sdelphij } 3083285612Sdelphij#endif 3084132451Sroberto 3085285612Sdelphij DPRINTF(4, ("bind(%d) AF_INET%s, addr %s%%%d#%d, flags 0x%x\n", 3086285612Sdelphij fd, IS_IPV6(addr) ? "6" : "", stoa(addr), 3087285612Sdelphij SCOPE(addr), SRCPORT(addr), interf->flags)); 3088285612Sdelphij 3089285612Sdelphij make_socket_nonblocking(fd); 3090285612Sdelphij 309154359Sroberto#ifdef HAVE_SIGNALED_IO 309254359Sroberto init_socket_sig(fd); 309354359Sroberto#endif /* not HAVE_SIGNALED_IO */ 309454359Sroberto 3095182007Sroberto add_fd_to_list(fd, FD_TYPE_SOCKET); 309654359Sroberto 309754359Sroberto#if !defined(SYS_WINNT) && !defined(VMS) 3098182007Sroberto DPRINTF(4, ("flags for fd %d: 0x%x\n", fd, 3099182007Sroberto fcntl(fd, F_GETFL, 0))); 310054359Sroberto#endif /* SYS_WINNT || VMS */ 310154359Sroberto 3102298699Sdelphij#if defined(HAVE_IO_COMPLETION_PORT) 310354359Sroberto/* 3104182007Sroberto * Add the socket to the completion port 310554359Sroberto */ 3106298699Sdelphij if (!io_completion_port_add_socket(fd, interf, bcast)) { 3107182007Sroberto msyslog(LOG_ERR, "unable to set up io completion port - EXITING"); 3108182007Sroberto exit(1); 310954359Sroberto } 3110132451Sroberto#endif 3111182007Sroberto return fd; 311254359Sroberto} 311354359Sroberto 3114285612Sdelphij 3115285612Sdelphij 311654359Sroberto/* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */ 311754359Sroberto/* 311854359Sroberto * sendpkt - send a packet to the specified destination. Maintain a 311954359Sroberto * send error cache so that only the first consecutive error for a 312054359Sroberto * destination is logged. 312154359Sroberto */ 312254359Srobertovoid 312354359Srobertosendpkt( 3124285612Sdelphij sockaddr_u * dest, 3125285612Sdelphij struct interface * ep, 3126285612Sdelphij int ttl, 3127285612Sdelphij struct pkt * pkt, 3128285612Sdelphij int len 312954359Sroberto ) 313054359Sroberto{ 3131285612Sdelphij endpt * src; 3132285612Sdelphij int ismcast; 3133285612Sdelphij int cc; 3134285612Sdelphij int rc; 3135285612Sdelphij u_char cttl; 3136338531Sdelphij l_fp fp_zero = { { 0 }, 0 }; 313754359Sroberto 3138285612Sdelphij ismcast = IS_MCAST(dest); 3139285612Sdelphij if (!ismcast) 3140285612Sdelphij src = ep; 3141285612Sdelphij else 3142285612Sdelphij src = (IS_IPV4(dest)) 3143285612Sdelphij ? mc4_list 3144285612Sdelphij : mc6_list; 314554359Sroberto 3146285612Sdelphij if (NULL == src) { 3147285612Sdelphij /* 3148285612Sdelphij * unbound peer - drop request and wait for better 3149285612Sdelphij * network conditions 3150285612Sdelphij */ 3151285612Sdelphij DPRINTF(2, ("%ssendpkt(dst=%s, ttl=%d, len=%d): no interface - IGNORED\n", 3152285612Sdelphij ismcast ? "\tMCAST\t***** " : "", 3153285612Sdelphij stoa(dest), ttl, len)); 3154285612Sdelphij return; 3155285612Sdelphij } 3156132451Sroberto 3157285612Sdelphij do { 3158285612Sdelphij DPRINTF(2, ("%ssendpkt(%d, dst=%s, src=%s, ttl=%d, len=%d)\n", 3159285612Sdelphij ismcast ? "\tMCAST\t***** " : "", src->fd, 3160285612Sdelphij stoa(dest), stoa(&src->sin), ttl, len)); 316154359Sroberto#ifdef MCAST 316282498Sroberto /* 3163285612Sdelphij * for the moment we use the bcast option to set multicast ttl 3164182007Sroberto */ 3165285612Sdelphij if (ismcast && ttl > 0 && ttl != src->last_ttl) { 316654359Sroberto /* 3167285612Sdelphij * set the multicast ttl for outgoing packets 316854359Sroberto */ 3169285612Sdelphij switch (AF(&src->sin)) { 3170132451Sroberto 3171132451Sroberto case AF_INET : 3172285612Sdelphij cttl = (u_char)ttl; 3173285612Sdelphij rc = setsockopt(src->fd, IPPROTO_IP, 3174285612Sdelphij IP_MULTICAST_TTL, 3175285612Sdelphij (void *)&cttl, 3176285612Sdelphij sizeof(cttl)); 3177132451Sroberto break; 3178132451Sroberto 3179285612Sdelphij# ifdef INCLUDE_IPV6_SUPPORT 3180132451Sroberto case AF_INET6 : 3181285612Sdelphij rc = setsockopt(src->fd, IPPROTO_IPV6, 3182285612Sdelphij IPV6_MULTICAST_HOPS, 3183285612Sdelphij (void *)&ttl, 3184285612Sdelphij sizeof(ttl)); 3185285612Sdelphij break; 3186285612Sdelphij# endif /* INCLUDE_IPV6_SUPPORT */ 3187132451Sroberto 3188285612Sdelphij default: 3189285612Sdelphij rc = 0; 3190132451Sroberto } 3191132451Sroberto 3192285612Sdelphij if (!rc) 3193285612Sdelphij src->last_ttl = ttl; 3194285612Sdelphij else 3195285612Sdelphij msyslog(LOG_ERR, 3196285612Sdelphij "setsockopt IP_MULTICAST_TTL/IPV6_MULTICAST_HOPS fails on address %s: %m", 3197285612Sdelphij stoa(&src->sin)); 319854359Sroberto } 3199285612Sdelphij#endif /* MCAST */ 3200285612Sdelphij 3201285612Sdelphij#ifdef SIM 3202285612Sdelphij cc = simulate_server(dest, src, pkt); 3203298699Sdelphij#elif defined(HAVE_IO_COMPLETION_PORT) 3204298699Sdelphij cc = io_completion_port_sendto(src, src->fd, pkt, 3205298699Sdelphij (size_t)len, (sockaddr_u *)&dest->sa); 3206285612Sdelphij#else 3207285612Sdelphij cc = sendto(src->fd, (char *)pkt, (u_int)len, 0, 3208285612Sdelphij &dest->sa, SOCKLEN(dest)); 3209285612Sdelphij#endif 3210285612Sdelphij if (cc == -1) { 3211285612Sdelphij src->notsent++; 3212285612Sdelphij packets_notsent++; 3213285612Sdelphij } else { 3214285612Sdelphij src->sent++; 3215285612Sdelphij packets_sent++; 321654359Sroberto } 3217285612Sdelphij if (ismcast) 3218285612Sdelphij src = src->mclink; 3219285612Sdelphij } while (ismcast && src != NULL); 3220330141Sdelphij 3221330141Sdelphij /* HMS: pkt->rootdisp is usually random here */ 3222330141Sdelphij record_raw_stats(src ? &src->sin : NULL, dest, 3223330141Sdelphij &pkt->org, &pkt->rec, &pkt->xmt, &fp_zero, 3224330141Sdelphij PKT_MODE(pkt->li_vn_mode), 3225330141Sdelphij PKT_VERSION(pkt->li_vn_mode), 3226330141Sdelphij PKT_LEAP(pkt->li_vn_mode), 3227330141Sdelphij pkt->stratum, 3228330141Sdelphij pkt->ppoll, pkt->precision, 3229330141Sdelphij pkt->rootdelay, pkt->rootdisp, pkt->refid, 3230330141Sdelphij len - MIN_V4_PKT_LEN, (u_char *)&pkt->exten); 3231330141Sdelphij 3232330141Sdelphij return; 323354359Sroberto} 323454359Sroberto 3235285612Sdelphij 3236298699Sdelphij#if !defined(HAVE_IO_COMPLETION_PORT) 3237298699Sdelphij#if !defined(HAVE_SIGNALED_IO) 323854359Sroberto/* 323954359Sroberto * fdbits - generate ascii representation of fd_set (FAU debug support) 324054359Sroberto * HFDF format - highest fd first. 324154359Sroberto */ 324254359Srobertostatic char * 324354359Srobertofdbits( 3244294569Sdelphij int count, 3245294569Sdelphij const fd_set* set 324654359Sroberto ) 324754359Sroberto{ 324854359Sroberto static char buffer[256]; 324954359Sroberto char * buf = buffer; 325054359Sroberto 3251285612Sdelphij count = min(count, 255); 325254359Sroberto 3253285612Sdelphij while (count >= 0) { 325454359Sroberto *buf++ = FD_ISSET(count, set) ? '#' : '-'; 325554359Sroberto count--; 325654359Sroberto } 325754359Sroberto *buf = '\0'; 325854359Sroberto 325954359Sroberto return buffer; 326054359Sroberto} 3261294569Sdelphij#endif 326254359Sroberto 3263285612Sdelphij#ifdef REFCLOCK 326454359Sroberto/* 3265182007Sroberto * Routine to read the refclock packets for a specific interface 3266182007Sroberto * Return the number of bytes read. That way we know if we should 3267182007Sroberto * read it again or go on to the next one if no bytes returned 326854359Sroberto */ 3269182007Srobertostatic inline int 3270285612Sdelphijread_refclock_packet( 3271285612Sdelphij SOCKET fd, 3272285612Sdelphij struct refclockio * rp, 3273285612Sdelphij l_fp ts 3274285612Sdelphij ) 327554359Sroberto{ 3276289997Sglebius u_int read_count; 3277285612Sdelphij int buflen; 3278285612Sdelphij int saved_errno; 3279285612Sdelphij int consumed; 3280285612Sdelphij struct recvbuf * rb; 328154359Sroberto 3282182007Sroberto rb = get_free_recv_buffer(); 328354359Sroberto 3284285612Sdelphij if (NULL == rb) { 328554359Sroberto /* 3286182007Sroberto * No buffer space available - just drop the packet 328754359Sroberto */ 3288182007Sroberto char buf[RX_BUFF_SIZE]; 328954359Sroberto 3290182007Sroberto buflen = read(fd, buf, sizeof buf); 3291182007Sroberto packets_dropped++; 3292182007Sroberto return (buflen); 3293182007Sroberto } 329454359Sroberto 3295289997Sglebius /* TALOS-CAN-0064: avoid signed/unsigned clashes that can lead 3296289997Sglebius * to buffer overrun and memory corruption 3297289997Sglebius */ 3298294569Sdelphij if (rp->datalen <= 0 || (size_t)rp->datalen > sizeof(rb->recv_space)) 3299289997Sglebius read_count = sizeof(rb->recv_space); 3300289997Sglebius else 3301289997Sglebius read_count = (u_int)rp->datalen; 3302285612Sdelphij do { 3303289997Sglebius buflen = read(fd, (char *)&rb->recv_space, read_count); 3304285612Sdelphij } while (buflen < 0 && EINTR == errno); 3305182007Sroberto 3306285612Sdelphij if (buflen <= 0) { 3307285612Sdelphij saved_errno = errno; 3308182007Sroberto freerecvbuf(rb); 3309285612Sdelphij errno = saved_errno; 3310285612Sdelphij return buflen; 3311182007Sroberto } 3312182007Sroberto 3313182007Sroberto /* 3314182007Sroberto * Got one. Mark how and when it got here, 3315182007Sroberto * put it on the full list and do bookkeeping. 3316182007Sroberto */ 3317182007Sroberto rb->recv_length = buflen; 3318285612Sdelphij rb->recv_peer = rp->srcclock; 3319182007Sroberto rb->dstadr = 0; 3320182007Sroberto rb->fd = fd; 3321182007Sroberto rb->recv_time = ts; 3322182007Sroberto rb->receiver = rp->clock_recv; 3323182007Sroberto 3324285612Sdelphij consumed = indicate_refclock_packet(rp, rb); 3325285612Sdelphij if (!consumed) { 3326285612Sdelphij rp->recvcount++; 3327285612Sdelphij packets_received++; 3328182007Sroberto } 332954359Sroberto 3330285612Sdelphij return buflen; 3331182007Sroberto} 3332285612Sdelphij#endif /* REFCLOCK */ 333354359Sroberto 3334285612Sdelphij 3335285612Sdelphij#ifdef HAVE_PACKET_TIMESTAMP 3336182007Sroberto/* 3337182007Sroberto * extract timestamps from control message buffer 3338182007Sroberto */ 3339182007Srobertostatic l_fp 3340285612Sdelphijfetch_timestamp( 3341285612Sdelphij struct recvbuf * rb, 3342285612Sdelphij struct msghdr * msghdr, 3343285612Sdelphij l_fp ts 3344285612Sdelphij ) 3345182007Sroberto{ 3346285612Sdelphij struct cmsghdr * cmsghdr; 3347285612Sdelphij unsigned long ticks; 3348285612Sdelphij double fuzz; 3349285612Sdelphij l_fp lfpfuzz; 3350285612Sdelphij l_fp nts; 3351285612Sdelphij#ifdef DEBUG_TIMING 3352285612Sdelphij l_fp dts; 3353285612Sdelphij#endif 335454359Sroberto 3355182007Sroberto cmsghdr = CMSG_FIRSTHDR(msghdr); 3356182007Sroberto while (cmsghdr != NULL) { 3357182007Sroberto switch (cmsghdr->cmsg_type) 3358182007Sroberto { 3359285612Sdelphij#ifdef HAVE_BINTIME 3360285612Sdelphij case SCM_BINTIME: 3361285612Sdelphij#endif /* HAVE_BINTIME */ 3362285612Sdelphij#ifdef HAVE_TIMESTAMPNS 3363285612Sdelphij case SCM_TIMESTAMPNS: 3364285612Sdelphij#endif /* HAVE_TIMESTAMPNS */ 3365285612Sdelphij#ifdef HAVE_TIMESTAMP 3366182007Sroberto case SCM_TIMESTAMP: 3367285612Sdelphij#endif /* HAVE_TIMESTAMP */ 3368285612Sdelphij#if defined(HAVE_BINTIME) || defined (HAVE_TIMESTAMPNS) || defined(HAVE_TIMESTAMP) 3369285612Sdelphij switch (cmsghdr->cmsg_type) 3370182007Sroberto { 3371285612Sdelphij#ifdef HAVE_BINTIME 3372285612Sdelphij case SCM_BINTIME: 3373301256Sdelphij { 3374301256Sdelphij struct bintime pbt; 3375301256Sdelphij memcpy(&pbt, CMSG_DATA(cmsghdr), sizeof(pbt)); 3376301256Sdelphij /* 3377301256Sdelphij * bintime documentation is at http://phk.freebsd.dk/pubs/timecounter.pdf 3378301256Sdelphij */ 3379301256Sdelphij nts.l_i = pbt.sec + JAN_1970; 3380301256Sdelphij nts.l_uf = (u_int32)(pbt.frac >> 32); 3381301256Sdelphij if (sys_tick > measured_tick && 3382301256Sdelphij sys_tick > 1e-9) { 3383301256Sdelphij ticks = (unsigned long)(nts.l_uf / (unsigned long)(sys_tick * FRAC)); 3384301256Sdelphij nts.l_uf = (unsigned long)(ticks * (unsigned long)(sys_tick * FRAC)); 3385301256Sdelphij } 3386301256Sdelphij DPRINTF(4, ("fetch_timestamp: system bintime network time stamp: %ld.%09lu\n", 3387301256Sdelphij pbt.sec, (unsigned long)((nts.l_uf / FRAC) * 1e9))); 3388285612Sdelphij } 3389285612Sdelphij break; 3390285612Sdelphij#endif /* HAVE_BINTIME */ 3391285612Sdelphij#ifdef HAVE_TIMESTAMPNS 3392285612Sdelphij case SCM_TIMESTAMPNS: 3393301256Sdelphij { 3394301256Sdelphij struct timespec pts; 3395301256Sdelphij memcpy(&pts, CMSG_DATA(cmsghdr), sizeof(pts)); 3396301256Sdelphij if (sys_tick > measured_tick && 3397301256Sdelphij sys_tick > 1e-9) { 3398301256Sdelphij ticks = (unsigned long)((pts.tv_nsec * 1e-9) / 3399301256Sdelphij sys_tick); 3400301256Sdelphij pts.tv_nsec = (long)(ticks * 1e9 * 3401301256Sdelphij sys_tick); 3402301256Sdelphij } 3403301256Sdelphij DPRINTF(4, ("fetch_timestamp: system nsec network time stamp: %ld.%09ld\n", 3404301256Sdelphij pts.tv_sec, pts.tv_nsec)); 3405301256Sdelphij nts = tspec_stamp_to_lfp(pts); 3406285612Sdelphij } 3407285612Sdelphij break; 3408285612Sdelphij#endif /* HAVE_TIMESTAMPNS */ 3409285612Sdelphij#ifdef HAVE_TIMESTAMP 3410285612Sdelphij case SCM_TIMESTAMP: 3411301256Sdelphij { 3412301256Sdelphij struct timeval ptv; 3413301256Sdelphij memcpy(&ptv, CMSG_DATA(cmsghdr), sizeof(ptv)); 3414301256Sdelphij if (sys_tick > measured_tick && 3415301256Sdelphij sys_tick > 1e-6) { 3416301256Sdelphij ticks = (unsigned long)((ptv.tv_usec * 1e-6) / 3417301256Sdelphij sys_tick); 3418301256Sdelphij ptv.tv_usec = (long)(ticks * 1e6 * 3419301256Sdelphij sys_tick); 3420301256Sdelphij } 3421301256Sdelphij DPRINTF(4, ("fetch_timestamp: system usec network time stamp: %jd.%06ld\n", 3422301256Sdelphij (intmax_t)ptv.tv_sec, (long)ptv.tv_usec)); 3423301256Sdelphij nts = tval_stamp_to_lfp(ptv); 3424285612Sdelphij } 3425285612Sdelphij break; 3426285612Sdelphij#endif /* HAVE_TIMESTAMP */ 3427182007Sroberto } 3428285612Sdelphij fuzz = ntp_random() * 2. / FRAC * sys_fuzz; 3429285612Sdelphij DTOLFP(fuzz, &lfpfuzz); 3430285612Sdelphij L_ADD(&nts, &lfpfuzz); 3431285612Sdelphij#ifdef DEBUG_TIMING 3432285612Sdelphij dts = ts; 3433285612Sdelphij L_SUB(&dts, &nts); 3434285612Sdelphij collect_timing(rb, "input processing delay", 1, 3435285612Sdelphij &dts); 3436285612Sdelphij DPRINTF(4, ("fetch_timestamp: timestamp delta: %s (incl. fuzz)\n", 3437285612Sdelphij lfptoa(&dts, 9))); 3438285612Sdelphij#endif /* DEBUG_TIMING */ 3439182007Sroberto ts = nts; /* network time stamp */ 3440182007Sroberto break; 3441285612Sdelphij#endif /* HAVE_BINTIME || HAVE_TIMESTAMPNS || HAVE_TIMESTAMP */ 3442285612Sdelphij 3443182007Sroberto default: 3444285612Sdelphij DPRINTF(4, ("fetch_timestamp: skipping control message 0x%x\n", 3445285612Sdelphij cmsghdr->cmsg_type)); 3446182007Sroberto } 3447182007Sroberto cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr); 3448182007Sroberto } 3449182007Sroberto return ts; 3450182007Sroberto} 3451285612Sdelphij#endif /* HAVE_PACKET_TIMESTAMP */ 345254359Sroberto 3453285612Sdelphij 3454182007Sroberto/* 3455182007Sroberto * Routine to read the network NTP packets for a specific interface 3456182007Sroberto * Return the number of bytes read. That way we know if we should 3457182007Sroberto * read it again or go on to the next one if no bytes returned 3458182007Sroberto */ 3459182007Srobertostatic inline int 3460285612Sdelphijread_network_packet( 3461285612Sdelphij SOCKET fd, 3462285612Sdelphij struct interface * itf, 3463285612Sdelphij l_fp ts 3464285612Sdelphij ) 3465182007Sroberto{ 3466182007Sroberto GETSOCKNAME_SOCKLEN_TYPE fromlen; 3467182007Sroberto int buflen; 3468182007Sroberto register struct recvbuf *rb; 3469285612Sdelphij#ifdef HAVE_PACKET_TIMESTAMP 3470182007Sroberto struct msghdr msghdr; 3471182007Sroberto struct iovec iovec; 3472285612Sdelphij char control[CMSG_BUFSIZE]; 347354359Sroberto#endif 347454359Sroberto 3475182007Sroberto /* 3476182007Sroberto * Get a buffer and read the frame. If we 3477182007Sroberto * haven't got a buffer, or this is received 3478182007Sroberto * on a disallowed socket, just dump the 3479182007Sroberto * packet. 3480182007Sroberto */ 348154359Sroberto 3482182007Sroberto rb = get_free_recv_buffer(); 3483285612Sdelphij if (NULL == rb || itf->ignore_packets) { 3484285612Sdelphij char buf[RX_BUFF_SIZE]; 3485285612Sdelphij sockaddr_u from; 348654359Sroberto 3487182007Sroberto if (rb != NULL) 3488182007Sroberto freerecvbuf(rb); 348954359Sroberto 3490182007Sroberto fromlen = sizeof(from); 3491182007Sroberto buflen = recvfrom(fd, buf, sizeof(buf), 0, 3492285612Sdelphij &from.sa, &fromlen); 3493182007Sroberto DPRINTF(4, ("%s on (%lu) fd=%d from %s\n", 3494285612Sdelphij (itf->ignore_packets) 3495285612Sdelphij ? "ignore" 3496285612Sdelphij : "drop", 3497285612Sdelphij free_recvbuffs(), fd, stoa(&from))); 3498285612Sdelphij if (itf->ignore_packets) 3499182007Sroberto packets_ignored++; 350054359Sroberto else 3501182007Sroberto packets_dropped++; 3502182007Sroberto return (buflen); 350354359Sroberto } 350454359Sroberto 3505285612Sdelphij fromlen = sizeof(rb->recv_srcadr); 350654359Sroberto 3507285612Sdelphij#ifndef HAVE_PACKET_TIMESTAMP 3508285612Sdelphij rb->recv_length = recvfrom(fd, (char *)&rb->recv_space, 3509285612Sdelphij sizeof(rb->recv_space), 0, 3510285612Sdelphij &rb->recv_srcadr.sa, &fromlen); 3511182007Sroberto#else 3512285612Sdelphij iovec.iov_base = &rb->recv_space; 3513182007Sroberto iovec.iov_len = sizeof(rb->recv_space); 3514285612Sdelphij msghdr.msg_name = &rb->recv_srcadr; 3515285612Sdelphij msghdr.msg_namelen = fromlen; 3516182007Sroberto msghdr.msg_iov = &iovec; 3517182007Sroberto msghdr.msg_iovlen = 1; 3518182007Sroberto msghdr.msg_control = (void *)&control; 3519182007Sroberto msghdr.msg_controllen = sizeof(control); 3520182007Sroberto msghdr.msg_flags = 0; 3521182007Sroberto rb->recv_length = recvmsg(fd, &msghdr, 0); 352254359Sroberto#endif 3523182007Sroberto 3524182007Sroberto buflen = rb->recv_length; 3525182007Sroberto 3526285612Sdelphij if (buflen == 0 || (buflen == -1 && 3527285612Sdelphij (EWOULDBLOCK == errno 352854359Sroberto#ifdef EAGAIN 3529285612Sdelphij || EAGAIN == errno 353054359Sroberto#endif 3531285612Sdelphij ))) { 353254359Sroberto freerecvbuf(rb); 3533182007Sroberto return (buflen); 3534285612Sdelphij } else if (buflen < 0) { 3535285612Sdelphij msyslog(LOG_ERR, "recvfrom(%s) fd=%d: %m", 3536285612Sdelphij stoa(&rb->recv_srcadr), fd); 3537285612Sdelphij DPRINTF(5, ("read_network_packet: fd=%d dropped (bad recvfrom)\n", 3538285612Sdelphij fd)); 353954359Sroberto freerecvbuf(rb); 3540182007Sroberto return (buflen); 354154359Sroberto } 3542182007Sroberto 3543285612Sdelphij DPRINTF(3, ("read_network_packet: fd=%d length %d from %s\n", 3544285612Sdelphij fd, buflen, stoa(&rb->recv_srcadr))); 3545285612Sdelphij 3546298699Sdelphij#ifdef ENABLE_BUG3020_FIX 3547298699Sdelphij if (ISREFCLOCKADR(&rb->recv_srcadr)) { 3548298699Sdelphij msyslog(LOG_ERR, "recvfrom(%s) fd=%d: refclock srcadr on a network interface!", 3549298699Sdelphij stoa(&rb->recv_srcadr), fd); 3550298699Sdelphij DPRINTF(1, ("read_network_packet: fd=%d dropped (refclock srcadr))\n", 3551298699Sdelphij fd)); 3552298699Sdelphij packets_dropped++; 3553298699Sdelphij freerecvbuf(rb); 3554298699Sdelphij return (buflen); 3555298699Sdelphij } 3556298699Sdelphij#endif 3557298699Sdelphij 3558285612Sdelphij /* 3559285612Sdelphij ** Bug 2672: Some OSes (MacOSX and Linux) don't block spoofed ::1 3560285612Sdelphij */ 3561285612Sdelphij 3562285612Sdelphij if (AF_INET6 == itf->family) { 3563285612Sdelphij DPRINTF(2, ("Got an IPv6 packet, from <%s> (%d) to <%s> (%d)\n", 3564285612Sdelphij stoa(&rb->recv_srcadr), 3565285612Sdelphij IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&rb->recv_srcadr)), 3566285612Sdelphij stoa(&itf->sin), 3567285612Sdelphij !IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&itf->sin)) 3568285612Sdelphij )); 3569285612Sdelphij 3570285612Sdelphij if ( IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&rb->recv_srcadr)) 3571285612Sdelphij && !IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&itf->sin)) 3572285612Sdelphij ) { 3573285612Sdelphij packets_dropped++; 3574285612Sdelphij DPRINTF(2, ("DROPPING that packet\n")); 3575285612Sdelphij freerecvbuf(rb); 3576285612Sdelphij return buflen; 3577285612Sdelphij } 3578285612Sdelphij DPRINTF(2, ("processing that packet\n")); 3579182007Sroberto } 358054359Sroberto 358154359Sroberto /* 358254359Sroberto * Got one. Mark how and when it got here, 358354359Sroberto * put it on the full list and do bookkeeping. 358454359Sroberto */ 3585182007Sroberto rb->dstadr = itf; 358654359Sroberto rb->fd = fd; 3587285612Sdelphij#ifdef HAVE_PACKET_TIMESTAMP 3588285612Sdelphij /* pick up a network time stamp if possible */ 3589285612Sdelphij ts = fetch_timestamp(rb, &msghdr, ts); 3590182007Sroberto#endif 359154359Sroberto rb->recv_time = ts; 359254359Sroberto rb->receiver = receive; 359354359Sroberto 359454359Sroberto add_full_recv_buffer(rb); 3595132451Sroberto 3596182007Sroberto itf->received++; 359754359Sroberto packets_received++; 3598182007Sroberto return (buflen); 3599182007Sroberto} 360054359Sroberto 3601182007Sroberto/* 3602285612Sdelphij * attempt to handle io (select()/signaled IO) 3603285612Sdelphij */ 3604285612Sdelphijvoid 3605285612Sdelphijio_handler(void) 3606285612Sdelphij{ 3607285612Sdelphij# ifndef HAVE_SIGNALED_IO 3608285612Sdelphij fd_set rdfdes; 3609285612Sdelphij int nfound; 3610285612Sdelphij 3611285612Sdelphij /* 3612285612Sdelphij * Use select() on all on all input fd's for unlimited 3613285612Sdelphij * time. select() will terminate on SIGALARM or on the 3614285612Sdelphij * reception of input. Using select() means we can't do 3615285612Sdelphij * robust signal handling and we get a potential race 3616285612Sdelphij * between checking for alarms and doing the select(). 3617285612Sdelphij * Mostly harmless, I think. 3618285612Sdelphij */ 3619285612Sdelphij /* 3620285612Sdelphij * On VMS, I suspect that select() can't be interrupted 3621285612Sdelphij * by a "signal" either, so I take the easy way out and 3622285612Sdelphij * have select() time out after one second. 3623285612Sdelphij * System clock updates really aren't time-critical, 3624285612Sdelphij * and - lacking a hardware reference clock - I have 3625285612Sdelphij * yet to learn about anything else that is. 3626285612Sdelphij */ 3627294569Sdelphij ++handler_calls; 3628285612Sdelphij rdfdes = activefds; 3629285612Sdelphij# if !defined(VMS) && !defined(SYS_VXWORKS) 3630285612Sdelphij nfound = select(maxactivefd + 1, &rdfdes, NULL, 3631285612Sdelphij NULL, NULL); 3632285612Sdelphij# else /* VMS, VxWorks */ 3633285612Sdelphij /* make select() wake up after one second */ 3634285612Sdelphij { 3635285612Sdelphij struct timeval t1; 3636294569Sdelphij t1.tv_sec = 1; 3637285612Sdelphij t1.tv_usec = 0; 3638285612Sdelphij nfound = select(maxactivefd + 1, 3639285612Sdelphij &rdfdes, NULL, NULL, 3640285612Sdelphij &t1); 3641285612Sdelphij } 3642285612Sdelphij# endif /* VMS, VxWorks */ 3643294569Sdelphij if (nfound < 0 && sanitize_fdset(errno)) { 3644294569Sdelphij struct timeval t1; 3645294569Sdelphij t1.tv_sec = 0; 3646294569Sdelphij t1.tv_usec = 0; 3647294569Sdelphij rdfdes = activefds; 3648294569Sdelphij nfound = select(maxactivefd + 1, 3649294569Sdelphij &rdfdes, NULL, NULL, 3650294569Sdelphij &t1); 3651294569Sdelphij } 3652294569Sdelphij 3653285612Sdelphij if (nfound > 0) { 3654285612Sdelphij l_fp ts; 3655285612Sdelphij 3656285612Sdelphij get_systime(&ts); 3657285612Sdelphij 3658294569Sdelphij input_handler_scan(&ts, &rdfdes); 3659285612Sdelphij } else if (nfound == -1 && errno != EINTR) { 3660285612Sdelphij msyslog(LOG_ERR, "select() error: %m"); 3661285612Sdelphij } 3662285612Sdelphij# ifdef DEBUG 3663285612Sdelphij else if (debug > 4) { 3664285612Sdelphij msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound); 3665285612Sdelphij } else { 3666285612Sdelphij DPRINTF(3, ("select() returned %d: %m\n", nfound)); 3667285612Sdelphij } 3668285612Sdelphij# endif /* DEBUG */ 3669285612Sdelphij# else /* HAVE_SIGNALED_IO */ 3670285612Sdelphij wait_for_signal(); 3671285612Sdelphij# endif /* HAVE_SIGNALED_IO */ 3672285612Sdelphij} 3673285612Sdelphij 3674294569Sdelphij#ifdef HAVE_SIGNALED_IO 3675285612Sdelphij/* 3676182007Sroberto * input_handler - receive packets asynchronously 3677294569Sdelphij * 3678294569Sdelphij * ALWAYS IN SIGNAL HANDLER CONTEXT -- only async-safe functions allowed! 3679182007Sroberto */ 3680294569Sdelphijstatic RETSIGTYPE 3681182007Srobertoinput_handler( 3682285612Sdelphij l_fp * cts 3683182007Sroberto ) 3684182007Sroberto{ 3685294569Sdelphij int n; 3686294569Sdelphij struct timeval tvzero; 3687294569Sdelphij fd_set fds; 3688294569Sdelphij 3689294569Sdelphij ++handler_calls; 3690294569Sdelphij 3691294569Sdelphij /* 3692294569Sdelphij * Do a poll to see who has data 3693294569Sdelphij */ 3694294569Sdelphij 3695294569Sdelphij fds = activefds; 3696294569Sdelphij tvzero.tv_sec = tvzero.tv_usec = 0; 3697294569Sdelphij 3698294569Sdelphij n = select(maxactivefd + 1, &fds, NULL, NULL, &tvzero); 3699294569Sdelphij if (n < 0 && sanitize_fdset(errno)) { 3700294569Sdelphij fds = activefds; 3701294569Sdelphij tvzero.tv_sec = tvzero.tv_usec = 0; 3702294569Sdelphij n = select(maxactivefd + 1, &fds, NULL, NULL, &tvzero); 3703294569Sdelphij } 3704294569Sdelphij if (n > 0) 3705294569Sdelphij input_handler_scan(cts, &fds); 3706294569Sdelphij} 3707294569Sdelphij#endif /* HAVE_SIGNALED_IO */ 3708294569Sdelphij 3709294569Sdelphij 3710294569Sdelphij/* 3711294569Sdelphij * Try to sanitize the global FD set 3712294569Sdelphij * 3713294569Sdelphij * SIGNAL HANDLER CONTEXT if HAVE_SIGNALED_IO, ordinary userspace otherwise 3714294569Sdelphij */ 3715294569Sdelphijstatic int/*BOOL*/ 3716294569Sdelphijsanitize_fdset( 3717294569Sdelphij int errc 3718294569Sdelphij ) 3719294569Sdelphij{ 3720294569Sdelphij int j, b, maxscan; 3721294569Sdelphij 3722294569Sdelphij# ifndef HAVE_SIGNALED_IO 3723294569Sdelphij /* 3724294569Sdelphij * extended FAU debugging output 3725294569Sdelphij */ 3726294569Sdelphij if (errc != EINTR) { 3727294569Sdelphij msyslog(LOG_ERR, 3728294569Sdelphij "select(%d, %s, 0L, 0L, &0.0) error: %m", 3729294569Sdelphij maxactivefd + 1, 3730294569Sdelphij fdbits(maxactivefd, &activefds)); 3731294569Sdelphij } 3732294569Sdelphij# endif 3733294569Sdelphij 3734294569Sdelphij if (errc != EBADF) 3735294569Sdelphij return FALSE; 3736294569Sdelphij 3737294569Sdelphij /* if we have oviously bad FDs, try to sanitize the FD set. */ 3738294569Sdelphij for (j = 0, maxscan = 0; j <= maxactivefd; j++) { 3739294569Sdelphij if (FD_ISSET(j, &activefds)) { 3740294569Sdelphij if (-1 != read(j, &b, 0)) { 3741294569Sdelphij maxscan = j; 3742294569Sdelphij continue; 3743294569Sdelphij } 3744294569Sdelphij# ifndef HAVE_SIGNALED_IO 3745294569Sdelphij msyslog(LOG_ERR, 3746294569Sdelphij "Removing bad file descriptor %d from select set", 3747294569Sdelphij j); 3748294569Sdelphij# endif 3749294569Sdelphij FD_CLR(j, &activefds); 3750294569Sdelphij } 3751294569Sdelphij } 3752294569Sdelphij if (maxactivefd != maxscan) 3753294569Sdelphij maxactivefd = maxscan; 3754294569Sdelphij return TRUE; 3755294569Sdelphij} 3756294569Sdelphij 3757294569Sdelphij/* 3758294569Sdelphij * scan the known FDs (clocks, servers, ...) for presence in a 'fd_set'. 3759294569Sdelphij * 3760294569Sdelphij * SIGNAL HANDLER CONTEXT if HAVE_SIGNALED_IO, ordinary userspace otherwise 3761294569Sdelphij */ 3762294569Sdelphijstatic void 3763294569Sdelphijinput_handler_scan( 3764294569Sdelphij const l_fp * cts, 3765294569Sdelphij const fd_set * pfds 3766294569Sdelphij ) 3767294569Sdelphij{ 3768285612Sdelphij int buflen; 3769285612Sdelphij u_int idx; 3770285612Sdelphij int doing; 3771285612Sdelphij SOCKET fd; 3772285612Sdelphij blocking_child *c; 3773285612Sdelphij l_fp ts; /* Timestamp at BOselect() gob */ 3774294569Sdelphij 3775294569Sdelphij#if defined(DEBUG_TIMING) 3776285612Sdelphij l_fp ts_e; /* Timestamp at EOselect() gob */ 3777182007Sroberto#endif 3778285612Sdelphij endpt * ep; 3779285612Sdelphij#ifdef REFCLOCK 3780285612Sdelphij struct refclockio *rp; 3781285612Sdelphij int saved_errno; 3782285612Sdelphij const char * clk; 3783182007Sroberto#endif 3784285612Sdelphij#ifdef HAS_ROUTING_SOCKET 3785285612Sdelphij struct asyncio_reader * asyncio_reader; 3786285612Sdelphij struct asyncio_reader * next_asyncio_reader; 3787285612Sdelphij#endif 3788182007Sroberto 3789294569Sdelphij ++handler_pkts; 3790182007Sroberto ts = *cts; 3791182007Sroberto 3792294569Sdelphij#ifdef REFCLOCK 3793182007Sroberto /* 3794294569Sdelphij * Check out the reference clocks first, if any 3795182007Sroberto */ 3796294569Sdelphij 3797294569Sdelphij for (rp = refio; rp != NULL; rp = rp->next) { 3798294569Sdelphij fd = rp->fd; 3799294569Sdelphij 3800294569Sdelphij if (!FD_ISSET(fd, pfds)) 3801294569Sdelphij continue; 3802294569Sdelphij buflen = read_refclock_packet(fd, rp, ts); 380354359Sroberto /* 3804294569Sdelphij * The first read must succeed after select() indicates 3805294569Sdelphij * readability, or we've reached a permanent EOF. 3806294569Sdelphij * http://bugs.ntp.org/1732 reported ntpd munching CPU 3807294569Sdelphij * after a USB GPS was unplugged because select was 3808294569Sdelphij * indicating EOF but ntpd didn't remove the descriptor 3809294569Sdelphij * from the activefds set. 381054359Sroberto */ 3811294569Sdelphij if (buflen < 0 && EAGAIN != errno) { 3812294569Sdelphij saved_errno = errno; 3813294569Sdelphij clk = refnumtoa(&rp->srcclock->srcadr); 3814294569Sdelphij errno = saved_errno; 3815294569Sdelphij msyslog(LOG_ERR, "%s read: %m", clk); 3816294569Sdelphij maintain_activefds(fd, TRUE); 3817294569Sdelphij } else if (0 == buflen) { 3818294569Sdelphij clk = refnumtoa(&rp->srcclock->srcadr); 3819294569Sdelphij msyslog(LOG_ERR, "%s read EOF", clk); 3820294569Sdelphij maintain_activefds(fd, TRUE); 3821294569Sdelphij } else { 3822294569Sdelphij /* drain any remaining refclock input */ 3823294569Sdelphij do { 3824294569Sdelphij buflen = read_refclock_packet(fd, rp, ts); 3825294569Sdelphij } while (buflen > 0); 3826182007Sroberto } 3827182007Sroberto } 3828182007Sroberto#endif /* REFCLOCK */ 382954359Sroberto 3830182007Sroberto /* 3831182007Sroberto * Loop through the interfaces looking for data to read. 3832182007Sroberto */ 3833285612Sdelphij for (ep = ep_list; ep != NULL; ep = ep->elink) { 3834285612Sdelphij for (doing = 0; doing < 2; doing++) { 3835285612Sdelphij if (!doing) { 3836285612Sdelphij fd = ep->fd; 3837285612Sdelphij } else { 3838285612Sdelphij if (!(ep->flags & INT_BCASTOPEN)) 3839285612Sdelphij break; 3840285612Sdelphij fd = ep->bfd; 384154359Sroberto } 3842285612Sdelphij if (fd < 0) 3843285612Sdelphij continue; 3844294569Sdelphij if (FD_ISSET(fd, pfds)) 3845182007Sroberto do { 3846285612Sdelphij buflen = read_network_packet( 3847285612Sdelphij fd, ep, ts); 3848182007Sroberto } while (buflen > 0); 3849285612Sdelphij /* Check more interfaces */ 385054359Sroberto } 385154359Sroberto } 3852182007Sroberto 3853182007Sroberto#ifdef HAS_ROUTING_SOCKET 3854182007Sroberto /* 3855182007Sroberto * scan list of asyncio readers - currently only used for routing sockets 3856182007Sroberto */ 3857285612Sdelphij asyncio_reader = asyncio_reader_list; 3858182007Sroberto 3859285612Sdelphij while (asyncio_reader != NULL) { 3860285612Sdelphij /* callback may unlink and free asyncio_reader */ 3861285612Sdelphij next_asyncio_reader = asyncio_reader->link; 3862294569Sdelphij if (FD_ISSET(asyncio_reader->fd, pfds)) 3863285612Sdelphij (*asyncio_reader->receiver)(asyncio_reader); 3864285612Sdelphij asyncio_reader = next_asyncio_reader; 3865182007Sroberto } 3866182007Sroberto#endif /* HAS_ROUTING_SOCKET */ 3867285612Sdelphij 3868182007Sroberto /* 3869285612Sdelphij * Check for a response from a blocking child 3870182007Sroberto */ 3871285612Sdelphij for (idx = 0; idx < blocking_children_alloc; idx++) { 3872285612Sdelphij c = blocking_children[idx]; 3873285612Sdelphij if (NULL == c || -1 == c->resp_read_pipe) 3874285612Sdelphij continue; 3875294569Sdelphij if (FD_ISSET(c->resp_read_pipe, pfds)) { 3876294569Sdelphij ++c->resp_ready_seen; 3877294569Sdelphij ++blocking_child_ready_seen; 3878285612Sdelphij } 3879285612Sdelphij } 3880182007Sroberto 3881285612Sdelphij /* We've done our work */ 3882294569Sdelphij#if defined(DEBUG_TIMING) 3883182007Sroberto get_systime(&ts_e); 3884182007Sroberto /* 3885182007Sroberto * (ts_e - ts) is the amount of time we spent 3886182007Sroberto * processing this gob of file descriptors. Log 3887182007Sroberto * it. 3888182007Sroberto */ 3889182007Sroberto L_SUB(&ts_e, &ts); 3890182007Sroberto collect_timing(NULL, "input handler", 1, &ts_e); 3891182007Sroberto if (debug > 3) 3892285612Sdelphij msyslog(LOG_DEBUG, 3893285612Sdelphij "input_handler: Processed a gob of fd's in %s msec", 3894285612Sdelphij lfptoms(&ts_e, 6)); 3895285612Sdelphij#endif /* DEBUG_TIMING */ 389654359Sroberto} 3897298699Sdelphij#endif /* !HAVE_IO_COMPLETION_PORT */ 389854359Sroberto 3899285612Sdelphij/* 3900285612Sdelphij * find an interface suitable for the src address 3901285612Sdelphij */ 3902285612Sdelphijendpt * 3903285612Sdelphijselect_peerinterface( 3904285612Sdelphij struct peer * peer, 3905285612Sdelphij sockaddr_u * srcadr, 3906285612Sdelphij endpt * dstadr 3907285612Sdelphij ) 3908285612Sdelphij{ 3909285612Sdelphij endpt *ep; 3910285612Sdelphij#ifndef SIM 3911285612Sdelphij endpt *wild; 3912285612Sdelphij 3913285612Sdelphij wild = ANY_INTERFACE_CHOOSE(srcadr); 3914285612Sdelphij 3915285612Sdelphij /* 3916285612Sdelphij * Initialize the peer structure and dance the interface jig. 3917285612Sdelphij * Reference clocks step the loopback waltz, the others 3918285612Sdelphij * squaredance around the interface list looking for a buddy. If 3919285612Sdelphij * the dance peters out, there is always the wildcard interface. 3920285612Sdelphij * This might happen in some systems and would preclude proper 3921285612Sdelphij * operation with public key cryptography. 3922285612Sdelphij */ 3923285612Sdelphij if (ISREFCLOCKADR(srcadr)) { 3924285612Sdelphij ep = loopback_interface; 3925285612Sdelphij } else if (peer->cast_flags & 3926285612Sdelphij (MDF_BCLNT | MDF_ACAST | MDF_MCAST | MDF_BCAST)) { 3927285612Sdelphij ep = findbcastinter(srcadr); 3928285612Sdelphij if (ep != NULL) 3929285612Sdelphij DPRINTF(4, ("Found *-cast interface %s for address %s\n", 3930285612Sdelphij stoa(&ep->sin), stoa(srcadr))); 3931285612Sdelphij else 3932285612Sdelphij DPRINTF(4, ("No *-cast local address found for address %s\n", 3933285612Sdelphij stoa(srcadr))); 3934285612Sdelphij } else { 3935285612Sdelphij ep = dstadr; 3936285612Sdelphij if (NULL == ep) 3937285612Sdelphij ep = wild; 3938285612Sdelphij } 3939285612Sdelphij /* 3940285612Sdelphij * If it is a multicast address, findbcastinter() may not find 3941285612Sdelphij * it. For unicast, we get to find the interface when dstadr is 3942285612Sdelphij * given to us as the wildcard (ANY_INTERFACE_CHOOSE). Either 3943285612Sdelphij * way, try a little harder. 3944285612Sdelphij */ 3945285612Sdelphij if (wild == ep) 3946285612Sdelphij ep = findinterface(srcadr); 3947285612Sdelphij /* 3948285612Sdelphij * we do not bind to the wildcard interfaces for output 3949285612Sdelphij * as our (network) source address would be undefined and 3950285612Sdelphij * crypto will not work without knowing the own transmit address 3951285612Sdelphij */ 3952285612Sdelphij if (ep != NULL && INT_WILDCARD & ep->flags) 3953285612Sdelphij if (!accept_wildcard_if_for_winnt) 3954285612Sdelphij ep = NULL; 3955285612Sdelphij#else /* SIM follows */ 3956285612Sdelphij ep = loopback_interface; 395754359Sroberto#endif 3958182007Sroberto 3959285612Sdelphij return ep; 3960285612Sdelphij} 3961285612Sdelphij 3962285612Sdelphij 396354359Sroberto/* 3964182007Sroberto * findinterface - find local interface corresponding to address 396554359Sroberto */ 3966285612Sdelphijendpt * 396754359Srobertofindinterface( 3968285612Sdelphij sockaddr_u *addr 396954359Sroberto ) 397054359Sroberto{ 3971285612Sdelphij endpt *iface; 3972182007Sroberto 3973285612Sdelphij iface = findlocalinterface(addr, INT_WILDCARD, 0); 3974285612Sdelphij 3975285612Sdelphij if (NULL == iface) { 3976182007Sroberto DPRINTF(4, ("Found no interface for address %s - returning wildcard\n", 3977182007Sroberto stoa(addr))); 3978182007Sroberto 3979285612Sdelphij iface = ANY_INTERFACE_CHOOSE(addr); 3980285612Sdelphij } else 3981182007Sroberto DPRINTF(4, ("Found interface #%d %s for address %s\n", 3982285612Sdelphij iface->ifnum, iface->name, stoa(addr))); 3983182007Sroberto 3984285612Sdelphij return iface; 3985182007Sroberto} 3986182007Sroberto 3987182007Sroberto/* 3988285612Sdelphij * findlocalinterface - find local interface corresponding to addr, 3989285612Sdelphij * which does not have any of flags set. If bast is nonzero, addr is 3990285612Sdelphij * a broadcast address. 3991182007Sroberto * 3992182007Sroberto * This code attempts to find the local sending address for an outgoing 3993182007Sroberto * address by connecting a new socket to destinationaddress:NTP_PORT 3994182007Sroberto * and reading the sockname of the resulting connect. 3995182007Sroberto * the complicated sequence simulates the routing table lookup 3996182007Sroberto * for to first hop without duplicating any of the routing logic into 3997182007Sroberto * ntpd. preferably we would have used an API call - but its not there - 3998182007Sroberto * so this is the best we can do here short of duplicating to entire routing 3999182007Sroberto * logic in ntpd which would be a silly and really unportable thing to do. 4000182007Sroberto * 4001182007Sroberto */ 4002285612Sdelphijstatic endpt * 4003182007Srobertofindlocalinterface( 4004285612Sdelphij sockaddr_u * addr, 4005285612Sdelphij int flags, 4006285612Sdelphij int bcast 4007182007Sroberto ) 4008182007Sroberto{ 4009285612Sdelphij GETSOCKNAME_SOCKLEN_TYPE sockaddrlen; 4010285612Sdelphij endpt * iface; 4011285612Sdelphij sockaddr_u saddr; 4012285612Sdelphij SOCKET s; 4013285612Sdelphij int rtn; 4014285612Sdelphij int on; 4015182007Sroberto 4016182007Sroberto DPRINTF(4, ("Finding interface for addr %s in list of addresses\n", 4017200576Sroberto stoa(addr))); 4018182007Sroberto 4019330141Sdelphij /* [Bug 3437] The dummy POOL peer comes in with an AF of 4020330141Sdelphij * zero. This is bound to fail, but on the way to nowhere it 4021330141Sdelphij * triggers a security incident on SELinux. 4022330141Sdelphij * 4023330141Sdelphij * Checking the condition and failing early is probably a good 4024330141Sdelphij * advice, and even saves us some syscalls in that case. 4025330141Sdelphij * Thanks to Miroslav Lichvar for finding this. 4026330141Sdelphij */ 4027330141Sdelphij if (AF_UNSPEC == AF(addr)) 4028330141Sdelphij return NULL; 4029330141Sdelphij 4030285612Sdelphij s = socket(AF(addr), SOCK_DGRAM, 0); 4031285612Sdelphij if (INVALID_SOCKET == s) 4032182007Sroberto return NULL; 4033132451Sroberto 4034285612Sdelphij /* 4035285612Sdelphij * If we are looking for broadcast interface we need to set this 4036285612Sdelphij * socket to allow broadcast 4037285612Sdelphij */ 4038285612Sdelphij if (bcast) { 4039285612Sdelphij on = 1; 4040285612Sdelphij if (SOCKET_ERROR == setsockopt(s, SOL_SOCKET, 4041285612Sdelphij SO_BROADCAST, 4042330141Sdelphij (void *)&on, 4043285612Sdelphij sizeof(on))) { 4044285612Sdelphij closesocket(s); 4045285612Sdelphij return NULL; 4046285612Sdelphij } 4047285612Sdelphij } 4048285612Sdelphij 4049285612Sdelphij rtn = connect(s, &addr->sa, SOCKLEN(addr)); 4050285612Sdelphij if (SOCKET_ERROR == rtn) { 4051132451Sroberto closesocket(s); 4052182007Sroberto return NULL; 4053132451Sroberto } 405482498Sroberto 4055285612Sdelphij sockaddrlen = sizeof(saddr); 4056285612Sdelphij rtn = getsockname(s, &saddr.sa, &sockaddrlen); 4057132451Sroberto closesocket(s); 4058285612Sdelphij if (SOCKET_ERROR == rtn) 4059182007Sroberto return NULL; 406082498Sroberto 4061285612Sdelphij DPRINTF(4, ("findlocalinterface: kernel maps %s to %s\n", 4062285612Sdelphij stoa(addr), stoa(&saddr))); 4063285612Sdelphij 4064182007Sroberto iface = getinterface(&saddr, flags); 4065182007Sroberto 4066285612Sdelphij /* 4067285612Sdelphij * if we didn't find an exact match on saddr, find the closest 4068285612Sdelphij * available local address. This handles the case of the 4069285612Sdelphij * address suggested by the kernel being excluded by nic rules 4070285612Sdelphij * or the user's -I and -L options to ntpd. 4071285612Sdelphij * See http://bugs.ntp.org/1184 and http://bugs.ntp.org/1683 4072285612Sdelphij * for more background. 4073285612Sdelphij */ 4074285612Sdelphij if (NULL == iface || iface->ignore_packets) 4075285612Sdelphij iface = findclosestinterface(&saddr, 4076285612Sdelphij flags | INT_LOOPBACK); 4077285612Sdelphij 4078285612Sdelphij /* Don't use an interface which will ignore replies */ 4079285612Sdelphij if (iface != NULL && iface->ignore_packets) 4080285612Sdelphij iface = NULL; 4081285612Sdelphij 4082285612Sdelphij return iface; 408354359Sroberto} 408454359Sroberto 4085285612Sdelphij 408654359Sroberto/* 4087285612Sdelphij * findclosestinterface 4088285612Sdelphij * 4089285612Sdelphij * If there are -I/--interface or -L/novirtualips command-line options, 4090285612Sdelphij * or "nic" or "interface" rules in ntp.conf, findlocalinterface() may 4091285612Sdelphij * find the kernel's preferred local address for a given peer address is 4092285612Sdelphij * administratively unavailable to ntpd, and punt to this routine's more 4093285612Sdelphij * expensive search. 4094285612Sdelphij * 4095285612Sdelphij * Find the numerically closest local address to the one connect() 4096285612Sdelphij * suggested. This matches an address on the same subnet first, as 4097285612Sdelphij * needed by Bug 1184, and provides a consistent choice if there are 4098285612Sdelphij * multiple feasible local addresses, regardless of the order ntpd 4099285612Sdelphij * enumerated them. 4100182007Sroberto */ 4101285612Sdelphijendpt * 4102285612Sdelphijfindclosestinterface( 4103285612Sdelphij sockaddr_u * addr, 4104285612Sdelphij int flags 4105285612Sdelphij ) 4106182007Sroberto{ 4107285612Sdelphij endpt * ep; 4108285612Sdelphij endpt * winner; 4109285612Sdelphij sockaddr_u addr_dist; 4110285612Sdelphij sockaddr_u min_dist; 4111182007Sroberto 4112285612Sdelphij ZERO_SOCK(&min_dist); 4113285612Sdelphij winner = NULL; 4114285612Sdelphij 4115285612Sdelphij for (ep = ep_list; ep != NULL; ep = ep->elink) { 4116285612Sdelphij if (ep->ignore_packets || 4117285612Sdelphij AF(addr) != ep->family || 4118285612Sdelphij flags & ep->flags) 4119285612Sdelphij continue; 4120285612Sdelphij 4121285612Sdelphij calc_addr_distance(&addr_dist, addr, &ep->sin); 4122285612Sdelphij if (NULL == winner || 4123285612Sdelphij -1 == cmp_addr_distance(&addr_dist, &min_dist)) { 4124285612Sdelphij min_dist = addr_dist; 4125285612Sdelphij winner = ep; 4126285612Sdelphij } 4127182007Sroberto } 4128285612Sdelphij if (NULL == winner) 4129285612Sdelphij DPRINTF(4, ("findclosestinterface(%s) failed\n", 4130285612Sdelphij stoa(addr))); 4131182007Sroberto else 4132285612Sdelphij DPRINTF(4, ("findclosestinterface(%s) -> %s\n", 4133285612Sdelphij stoa(addr), stoa(&winner->sin))); 4134285612Sdelphij 4135285612Sdelphij return winner; 4136182007Sroberto} 4137182007Sroberto 4138285612Sdelphij 4139182007Sroberto/* 4140285612Sdelphij * calc_addr_distance - calculate the distance between two addresses, 4141285612Sdelphij * the absolute value of the difference between 4142285612Sdelphij * the addresses numerically, stored as an address. 4143182007Sroberto */ 4144285612Sdelphijstatic void 4145285612Sdelphijcalc_addr_distance( 4146285612Sdelphij sockaddr_u * dist, 4147285612Sdelphij const sockaddr_u * a1, 4148285612Sdelphij const sockaddr_u * a2 4149182007Sroberto ) 4150182007Sroberto{ 4151285612Sdelphij u_int32 a1val; 4152285612Sdelphij u_int32 a2val; 4153285612Sdelphij u_int32 v4dist; 4154285612Sdelphij int found_greater; 4155285612Sdelphij int a1_greater; 4156285612Sdelphij int i; 4157182007Sroberto 4158289997Sglebius REQUIRE(AF(a1) == AF(a2)); 4159182007Sroberto 4160285612Sdelphij ZERO_SOCK(dist); 4161285612Sdelphij AF(dist) = AF(a1); 4162285612Sdelphij 4163285612Sdelphij /* v4 can be done a bit simpler */ 4164285612Sdelphij if (IS_IPV4(a1)) { 4165285612Sdelphij a1val = SRCADR(a1); 4166285612Sdelphij a2val = SRCADR(a2); 4167285612Sdelphij v4dist = (a1val > a2val) 4168285612Sdelphij ? a1val - a2val 4169285612Sdelphij : a2val - a1val; 4170285612Sdelphij SET_ADDR4(dist, v4dist); 4171285612Sdelphij 4172285612Sdelphij return; 4173182007Sroberto } 4174182007Sroberto 4175285612Sdelphij found_greater = FALSE; 4176285612Sdelphij a1_greater = FALSE; /* suppress pot. uninit. warning */ 4177285612Sdelphij for (i = 0; i < (int)sizeof(NSRCADR6(a1)); i++) { 4178285612Sdelphij if (!found_greater && 4179285612Sdelphij NSRCADR6(a1)[i] != NSRCADR6(a2)[i]) { 4180285612Sdelphij found_greater = TRUE; 4181285612Sdelphij a1_greater = (NSRCADR6(a1)[i] > NSRCADR6(a2)[i]); 4182182007Sroberto } 4183285612Sdelphij if (!found_greater) { 4184285612Sdelphij NSRCADR6(dist)[i] = 0; 4185285612Sdelphij } else { 4186285612Sdelphij if (a1_greater) 4187285612Sdelphij NSRCADR6(dist)[i] = NSRCADR6(a1)[i] - 4188285612Sdelphij NSRCADR6(a2)[i]; 4189285612Sdelphij else 4190285612Sdelphij NSRCADR6(dist)[i] = NSRCADR6(a2)[i] - 4191285612Sdelphij NSRCADR6(a1)[i]; 4192182007Sroberto } 4193182007Sroberto } 4194285612Sdelphij} 4195182007Sroberto 4196182007Sroberto 4197285612Sdelphij/* 4198285612Sdelphij * cmp_addr_distance - compare two address distances, returning -1, 0, 4199285612Sdelphij * 1 to indicate their relationship. 4200285612Sdelphij */ 4201285612Sdelphijstatic int 4202285612Sdelphijcmp_addr_distance( 4203285612Sdelphij const sockaddr_u * d1, 4204285612Sdelphij const sockaddr_u * d2 4205285612Sdelphij ) 4206285612Sdelphij{ 4207285612Sdelphij int i; 4208182007Sroberto 4209289997Sglebius REQUIRE(AF(d1) == AF(d2)); 4210182007Sroberto 4211285612Sdelphij if (IS_IPV4(d1)) { 4212285612Sdelphij if (SRCADR(d1) < SRCADR(d2)) 4213285612Sdelphij return -1; 4214285612Sdelphij else if (SRCADR(d1) == SRCADR(d2)) 4215285612Sdelphij return 0; 4216285612Sdelphij else 4217285612Sdelphij return 1; 4218285612Sdelphij } 4219182007Sroberto 4220285612Sdelphij for (i = 0; i < (int)sizeof(NSRCADR6(d1)); i++) { 4221285612Sdelphij if (NSRCADR6(d1)[i] < NSRCADR6(d2)[i]) 4222285612Sdelphij return -1; 4223285612Sdelphij else if (NSRCADR6(d1)[i] > NSRCADR6(d2)[i]) 4224285612Sdelphij return 1; 4225182007Sroberto } 4226285612Sdelphij 4227285612Sdelphij return 0; 4228182007Sroberto} 4229182007Sroberto 4230285612Sdelphij 4231285612Sdelphij 4232182007Sroberto/* 4233285612Sdelphij * fetch an interface structure the matches the 4234285612Sdelphij * address and has the given flags NOT set 4235285612Sdelphij */ 4236285612Sdelphijendpt * 4237285612Sdelphijgetinterface( 4238285612Sdelphij sockaddr_u * addr, 4239285612Sdelphij u_int32 flags 4240285612Sdelphij ) 4241285612Sdelphij{ 4242285612Sdelphij endpt *iface; 4243285612Sdelphij 4244285612Sdelphij iface = find_addr_in_list(addr); 4245285612Sdelphij 4246285612Sdelphij if (iface != NULL && (iface->flags & flags)) 4247285612Sdelphij iface = NULL; 4248285612Sdelphij 4249285612Sdelphij return iface; 4250285612Sdelphij} 4251285612Sdelphij 4252285612Sdelphij 4253285612Sdelphij/* 425482498Sroberto * findbcastinter - find broadcast interface corresponding to address 425582498Sroberto */ 4256285612Sdelphijendpt * 425782498Srobertofindbcastinter( 4258285612Sdelphij sockaddr_u *addr 425982498Sroberto ) 426082498Sroberto{ 4261285612Sdelphij endpt * iface; 4262285612Sdelphij 4263285612Sdelphij iface = NULL; 4264106163Sroberto#if !defined(MPE) && (defined(SIOCGIFCONF) || defined(SYS_WINNT)) 4265182007Sroberto DPRINTF(4, ("Finding broadcast/multicast interface for addr %s in list of addresses\n", 4266182007Sroberto stoa(addr))); 426782498Sroberto 4268285612Sdelphij iface = findlocalinterface(addr, INT_LOOPBACK | INT_WILDCARD, 4269285612Sdelphij 1); 4270285612Sdelphij if (iface != NULL) { 4271285612Sdelphij DPRINTF(4, ("Easily found bcast-/mcast- interface index #%d %s\n", 4272285612Sdelphij iface->ifnum, iface->name)); 4273285612Sdelphij return iface; 4274182007Sroberto } 4275182007Sroberto 4276285612Sdelphij /* 4277285612Sdelphij * plan B - try to find something reasonable in our lists in 4278285612Sdelphij * case kernel lookup doesn't help 4279285612Sdelphij */ 4280285612Sdelphij for (iface = ep_list; iface != NULL; iface = iface->elink) { 4281285612Sdelphij if (iface->flags & INT_WILDCARD) 4282285612Sdelphij continue; 4283182007Sroberto 4284182007Sroberto /* Don't bother with ignored interfaces */ 4285285612Sdelphij if (iface->ignore_packets) 4286182007Sroberto continue; 4287285612Sdelphij 428882498Sroberto /* 4289182007Sroberto * First look if this is the correct family 4290182007Sroberto */ 4291285612Sdelphij if(AF(&iface->sin) != AF(addr)) 4292285612Sdelphij continue; 4293182007Sroberto 4294182007Sroberto /* Skip the loopback addresses */ 4295285612Sdelphij if (iface->flags & INT_LOOPBACK) 4296182007Sroberto continue; 4297182007Sroberto 4298132451Sroberto /* 4299285612Sdelphij * If we are looking to match a multicast address and 4300285612Sdelphij * this interface is one... 4301182007Sroberto */ 4302285612Sdelphij if (addr_ismulticast(addr) 4303285612Sdelphij && (iface->flags & INT_MULTICAST)) { 4304182007Sroberto#ifdef INCLUDE_IPV6_SUPPORT 4305285612Sdelphij /* 4306285612Sdelphij * ...it is the winner unless we're looking for 4307285612Sdelphij * an interface to use for link-local multicast 4308285612Sdelphij * and its address is not link-local. 4309285612Sdelphij */ 4310285612Sdelphij if (IS_IPV6(addr) 4311285612Sdelphij && IN6_IS_ADDR_MC_LINKLOCAL(PSOCK_ADDR6(addr)) 4312285612Sdelphij && !IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(&iface->sin))) 4313285612Sdelphij continue; 4314182007Sroberto#endif 4315182007Sroberto break; 4316182007Sroberto } 4317182007Sroberto 4318182007Sroberto /* 431982498Sroberto * We match only those interfaces marked as 432082498Sroberto * broadcastable and either the explicit broadcast 432182498Sroberto * address or the network portion of the IP address. 432282498Sroberto * Sloppy. 432382498Sroberto */ 4324285612Sdelphij if (IS_IPV4(addr)) { 4325285612Sdelphij if (SOCK_EQ(&iface->bcast, addr)) 4326182007Sroberto break; 4327285612Sdelphij 4328285612Sdelphij if ((NSRCADR(&iface->sin) & NSRCADR(&iface->mask)) 4329285612Sdelphij == (NSRCADR(addr) & NSRCADR(&iface->mask))) 4330182007Sroberto break; 4331132451Sroberto } 4332182007Sroberto#ifdef INCLUDE_IPV6_SUPPORT 4333285612Sdelphij else if (IS_IPV6(addr)) { 4334285612Sdelphij if (SOCK_EQ(&iface->bcast, addr)) 4335182007Sroberto break; 4336285612Sdelphij 4337285612Sdelphij if (SOCK_EQ(netof(&iface->sin), netof(addr))) 4338182007Sroberto break; 4339182007Sroberto } 4340182007Sroberto#endif 434182498Sroberto } 434282498Sroberto#endif /* SIOCGIFCONF */ 4343285612Sdelphij if (NULL == iface) { 4344285612Sdelphij DPRINTF(4, ("No bcast interface found for %s\n", 4345285612Sdelphij stoa(addr))); 4346285612Sdelphij iface = ANY_INTERFACE_CHOOSE(addr); 4347182007Sroberto } else { 4348285612Sdelphij DPRINTF(4, ("Found bcast-/mcast- interface index #%d %s\n", 4349285612Sdelphij iface->ifnum, iface->name)); 4350182007Sroberto } 4351285612Sdelphij 4352285612Sdelphij return iface; 435382498Sroberto} 435482498Sroberto 435582498Sroberto 435682498Sroberto/* 435754359Sroberto * io_clr_stats - clear I/O module statistics 435854359Sroberto */ 435954359Srobertovoid 436054359Srobertoio_clr_stats(void) 436154359Sroberto{ 436254359Sroberto packets_dropped = 0; 436354359Sroberto packets_ignored = 0; 436454359Sroberto packets_received = 0; 436554359Sroberto packets_sent = 0; 436654359Sroberto packets_notsent = 0; 436754359Sroberto 436854359Sroberto handler_calls = 0; 436954359Sroberto handler_pkts = 0; 437054359Sroberto io_timereset = current_time; 437154359Sroberto} 437254359Sroberto 437354359Sroberto 437454359Sroberto#ifdef REFCLOCK 437554359Sroberto/* 437654359Sroberto * io_addclock - add a reference clock to the list and arrange that we 437754359Sroberto * get SIGIO interrupts from it. 437854359Sroberto */ 437954359Srobertoint 438054359Srobertoio_addclock( 438154359Sroberto struct refclockio *rio 438254359Sroberto ) 438354359Sroberto{ 438454359Sroberto BLOCKIO(); 4385285612Sdelphij 438654359Sroberto /* 438754359Sroberto * Stuff the I/O structure in the list and mark the descriptor 4388285612Sdelphij * in use. There is a harmless (I hope) race condition here. 438954359Sroberto */ 4390285612Sdelphij rio->active = TRUE; 439154359Sroberto 439254359Sroberto# ifdef HAVE_SIGNALED_IO 4393285612Sdelphij if (init_clock_sig(rio)) { 439454359Sroberto UNBLOCKIO(); 439554359Sroberto return 0; 439654359Sroberto } 439754359Sroberto# elif defined(HAVE_IO_COMPLETION_PORT) 4398298699Sdelphij if (!io_completion_port_add_clock_io(rio)) { 439954359Sroberto UNBLOCKIO(); 440054359Sroberto return 0; 440154359Sroberto } 440254359Sroberto# endif 440354359Sroberto 4404132451Sroberto /* 4405182007Sroberto * enqueue 4406132451Sroberto */ 4407285612Sdelphij LINK_SLIST(refio, rio, next); 4408182007Sroberto 4409285612Sdelphij /* 4410182007Sroberto * register fd 4411182007Sroberto */ 4412182007Sroberto add_fd_to_list(rio->fd, FD_TYPE_FILE); 4413182007Sroberto 441454359Sroberto UNBLOCKIO(); 441554359Sroberto return 1; 441654359Sroberto} 441754359Sroberto 4418285612Sdelphij 441954359Sroberto/* 442054359Sroberto * io_closeclock - close the clock in the I/O structure given 442154359Sroberto */ 442254359Srobertovoid 442354359Srobertoio_closeclock( 442454359Sroberto struct refclockio *rio 442554359Sroberto ) 442654359Sroberto{ 4427285612Sdelphij struct refclockio *unlinked; 4428285612Sdelphij 4429182007Sroberto BLOCKIO(); 4430285612Sdelphij 443154359Sroberto /* 443254359Sroberto * Remove structure from the list 443354359Sroberto */ 4434285612Sdelphij rio->active = FALSE; 4435285612Sdelphij UNLINK_SLIST(unlinked, refio, rio, next, struct refclockio); 4436285612Sdelphij if (NULL != unlinked) { 4437298699Sdelphij /* Close the descriptor. The order of operations is 4438298699Sdelphij * important here in case of async / overlapped IO: 4439298699Sdelphij * only after we have removed the clock from the 4440298699Sdelphij * IO completion port we can be sure no further 4441298699Sdelphij * input is queued. So... 4442298699Sdelphij * - we first disable feeding to the queu by removing 4443298699Sdelphij * the clock from the IO engine 4444298699Sdelphij * - close the file (which brings down any IO on it) 4445298699Sdelphij * - clear the buffer from results for this fd 4446285612Sdelphij */ 4447298699Sdelphij# ifdef HAVE_IO_COMPLETION_PORT 4448298699Sdelphij io_completion_port_remove_clock_io(rio); 4449298699Sdelphij# endif 4450285612Sdelphij close_and_delete_fd_from_list(rio->fd); 4451298699Sdelphij purge_recv_buffers_for_fd(rio->fd); 4452298699Sdelphij rio->fd = -1; 445354359Sroberto } 445454359Sroberto 4455182007Sroberto UNBLOCKIO(); 445654359Sroberto} 445754359Sroberto#endif /* REFCLOCK */ 445854359Sroberto 4459285612Sdelphij 4460132451Sroberto/* 4461132451Sroberto * On NT a SOCKET is an unsigned int so we cannot possibly keep it in 4462132451Sroberto * an array. So we use one of the ISC_LIST functions to hold the 4463132451Sroberto * socket value and use that when we want to enumerate it. 4464285612Sdelphij * 4465285612Sdelphij * This routine is called by the forked intres child process to close 4466285612Sdelphij * all open sockets. On Windows there's no need as intres runs in 4467285612Sdelphij * the same process as a thread. 4468132451Sroberto */ 4469285612Sdelphij#ifndef SYS_WINNT 4470132451Srobertovoid 4471285612Sdelphijkill_asyncio( 4472285612Sdelphij int startfd 4473285612Sdelphij ) 4474132451Sroberto{ 4475132451Sroberto BLOCKIO(); 4476132451Sroberto 4477285612Sdelphij /* 4478285612Sdelphij * In the child process we do not maintain activefds and 4479285612Sdelphij * maxactivefd. Zeroing maxactivefd disables code which 4480285612Sdelphij * maintains it in close_and_delete_fd_from_list(). 4481285612Sdelphij */ 4482285612Sdelphij maxactivefd = 0; 4483132451Sroberto 4484285612Sdelphij while (fd_list != NULL) 4485285612Sdelphij close_and_delete_fd_from_list(fd_list->fd); 4486285612Sdelphij 4487182007Sroberto UNBLOCKIO(); 4488132451Sroberto} 4489285612Sdelphij#endif /* !SYS_WINNT */ 4490182007Sroberto 4491285612Sdelphij 4492132451Sroberto/* 4493132451Sroberto * Add and delete functions for the list of open sockets 4494132451Sroberto */ 4495182007Srobertostatic void 4496285612Sdelphijadd_fd_to_list( 4497285612Sdelphij SOCKET fd, 4498285612Sdelphij enum desc_type type 4499285612Sdelphij ) 4500285612Sdelphij{ 4501285612Sdelphij vsock_t *lsock = emalloc(sizeof(*lsock)); 4502285612Sdelphij 4503132451Sroberto lsock->fd = fd; 4504182007Sroberto lsock->type = type; 4505132451Sroberto 4506285612Sdelphij LINK_SLIST(fd_list, lsock, link); 4507285612Sdelphij maintain_activefds(fd, 0); 4508132451Sroberto} 4509132451Sroberto 4510285612Sdelphij 4511182007Srobertostatic void 4512285612Sdelphijclose_and_delete_fd_from_list( 4513285612Sdelphij SOCKET fd 4514285612Sdelphij ) 4515285612Sdelphij{ 4516285612Sdelphij vsock_t *lsock; 4517182007Sroberto 4518285612Sdelphij UNLINK_EXPR_SLIST(lsock, fd_list, fd == 4519285612Sdelphij UNLINK_EXPR_SLIST_CURRENT()->fd, link, vsock_t); 4520132451Sroberto 4521285612Sdelphij if (NULL == lsock) 4522285612Sdelphij return; 4523182007Sroberto 4524285612Sdelphij switch (lsock->type) { 4525182007Sroberto 4526285612Sdelphij case FD_TYPE_SOCKET: 4527285612Sdelphij closesocket(lsock->fd); 4528285612Sdelphij break; 4529285612Sdelphij 4530285612Sdelphij case FD_TYPE_FILE: 4531293650Sglebius closeserial((int)lsock->fd); 4532285612Sdelphij break; 4533285612Sdelphij 4534285612Sdelphij default: 4535285612Sdelphij msyslog(LOG_ERR, 4536285612Sdelphij "internal error - illegal descriptor type %d - EXITING", 4537285612Sdelphij (int)lsock->type); 4538285612Sdelphij exit(1); 4539132451Sroberto } 4540285612Sdelphij 4541285612Sdelphij free(lsock); 4542285612Sdelphij /* 4543285612Sdelphij * remove from activefds 4544285612Sdelphij */ 4545285612Sdelphij maintain_activefds(fd, 1); 4546132451Sroberto} 4547132451Sroberto 4548285612Sdelphij 4549182007Srobertostatic void 4550285612Sdelphijadd_addr_to_list( 4551285612Sdelphij sockaddr_u * addr, 4552285612Sdelphij endpt * ep 4553285612Sdelphij ) 4554285612Sdelphij{ 4555285612Sdelphij remaddr_t *laddr; 4556285612Sdelphij 4557132451Sroberto#ifdef DEBUG 4558182007Sroberto if (find_addr_in_list(addr) == NULL) { 4559132451Sroberto#endif 4560182007Sroberto /* not there yet - add to list */ 4561285612Sdelphij laddr = emalloc(sizeof(*laddr)); 4562285612Sdelphij laddr->addr = *addr; 4563285612Sdelphij laddr->ep = ep; 4564285612Sdelphij 4565285612Sdelphij LINK_SLIST(remoteaddr_list, laddr, link); 4566285612Sdelphij 4567182007Sroberto DPRINTF(4, ("Added addr %s to list of addresses\n", 4568182007Sroberto stoa(addr))); 4569182007Sroberto#ifdef DEBUG 4570285612Sdelphij } else 4571182007Sroberto DPRINTF(4, ("WARNING: Attempt to add duplicate addr %s to address list\n", 4572182007Sroberto stoa(addr))); 4573182007Sroberto#endif 4574182007Sroberto} 4575132451Sroberto 4576285612Sdelphij 4577182007Srobertostatic void 4578285612Sdelphijdelete_addr_from_list( 4579285612Sdelphij sockaddr_u *addr 4580285612Sdelphij ) 4581285612Sdelphij{ 4582285612Sdelphij remaddr_t *unlinked; 4583132451Sroberto 4584285612Sdelphij UNLINK_EXPR_SLIST(unlinked, remoteaddr_list, SOCK_EQ(addr, 4585285612Sdelphij &(UNLINK_EXPR_SLIST_CURRENT()->addr)), link, remaddr_t); 4586132451Sroberto 4587285612Sdelphij if (unlinked != NULL) { 4588285612Sdelphij DPRINTF(4, ("Deleted addr %s from list of addresses\n", 4589285612Sdelphij stoa(addr))); 4590285612Sdelphij free(unlinked); 4591182007Sroberto } 4592182007Sroberto} 4593182007Sroberto 4594285612Sdelphij 4595182007Srobertostatic void 4596285612Sdelphijdelete_interface_from_list( 4597285612Sdelphij endpt *iface 4598285612Sdelphij ) 4599285612Sdelphij{ 4600285612Sdelphij remaddr_t *unlinked; 4601182007Sroberto 4602285612Sdelphij for (;;) { 4603285612Sdelphij UNLINK_EXPR_SLIST(unlinked, remoteaddr_list, iface == 4604285612Sdelphij UNLINK_EXPR_SLIST_CURRENT()->ep, link, 4605285612Sdelphij remaddr_t); 4606285612Sdelphij 4607285612Sdelphij if (unlinked == NULL) 4608285612Sdelphij break; 4609285612Sdelphij DPRINTF(4, ("Deleted addr %s for interface #%d %s from list of addresses\n", 4610285612Sdelphij stoa(&unlinked->addr), iface->ifnum, 4611285612Sdelphij iface->name)); 4612285612Sdelphij free(unlinked); 4613182007Sroberto } 4614182007Sroberto} 4615182007Sroberto 4616285612Sdelphij 4617182007Srobertostatic struct interface * 4618285612Sdelphijfind_addr_in_list( 4619285612Sdelphij sockaddr_u *addr 4620285612Sdelphij ) 4621285612Sdelphij{ 4622285612Sdelphij remaddr_t *entry; 4623182007Sroberto 4624182007Sroberto DPRINTF(4, ("Searching for addr %s in list of addresses - ", 4625182007Sroberto stoa(addr))); 4626182007Sroberto 4627285612Sdelphij for (entry = remoteaddr_list; 4628285612Sdelphij entry != NULL; 4629285612Sdelphij entry = entry->link) 4630285612Sdelphij if (SOCK_EQ(&entry->addr, addr)) { 4631182007Sroberto DPRINTF(4, ("FOUND\n")); 4632285612Sdelphij return entry->ep; 4633182007Sroberto } 4634285612Sdelphij 4635182007Sroberto DPRINTF(4, ("NOT FOUND\n")); 4636285612Sdelphij return NULL; 4637132451Sroberto} 4638132451Sroberto 4639285612Sdelphij 4640182007Sroberto/* 4641285612Sdelphij * Find the given address with the all given flags set in the list 4642182007Sroberto */ 4643285612Sdelphijstatic endpt * 4644285612Sdelphijfind_flagged_addr_in_list( 4645285612Sdelphij sockaddr_u * addr, 4646285612Sdelphij u_int32 flags 4647285612Sdelphij ) 4648285612Sdelphij{ 4649285612Sdelphij remaddr_t *entry; 4650182007Sroberto 4651285612Sdelphij DPRINTF(4, ("Finding addr %s with flags %d in list: ", 4652285612Sdelphij stoa(addr), flags)); 4653132451Sroberto 4654285612Sdelphij for (entry = remoteaddr_list; 4655285612Sdelphij entry != NULL; 4656285612Sdelphij entry = entry->link) 4657285612Sdelphij 4658285612Sdelphij if (SOCK_EQ(&entry->addr, addr) 4659285612Sdelphij && (entry->ep->flags & flags) == flags) { 4660285612Sdelphij 4661285612Sdelphij DPRINTF(4, ("FOUND\n")); 4662285612Sdelphij return entry->ep; 4663132451Sroberto } 4664285612Sdelphij 4665285612Sdelphij DPRINTF(4, ("NOT FOUND\n")); 4666285612Sdelphij return NULL; 4667132451Sroberto} 4668182007Sroberto 4669285612Sdelphij 4670285612Sdelphijconst char * 4671285612Sdelphijlocaladdrtoa( 4672285612Sdelphij endpt *la 4673285612Sdelphij ) 4674285612Sdelphij{ 4675285612Sdelphij return (NULL == la) 4676285612Sdelphij ? "<null>" 4677285612Sdelphij : stoa(&la->sin); 4678285612Sdelphij} 4679285612Sdelphij 4680285612Sdelphij 4681182007Sroberto#ifdef HAS_ROUTING_SOCKET 4682285612Sdelphij# ifndef UPDATE_GRACE 4683285612Sdelphij# define UPDATE_GRACE 2 /* wait UPDATE_GRACE seconds before scanning */ 4684285612Sdelphij# endif 4685182007Sroberto 4686182007Srobertostatic void 4687182007Srobertoprocess_routing_msgs(struct asyncio_reader *reader) 4688182007Sroberto{ 4689182007Sroberto char buffer[5120]; 4690285612Sdelphij int cnt, msg_type; 4691285612Sdelphij#ifdef HAVE_RTNETLINK 4692285612Sdelphij struct nlmsghdr *nh; 4693285612Sdelphij#else 4694285612Sdelphij struct rt_msghdr rtm; 4695285612Sdelphij char *p; 4696285612Sdelphij#endif 4697182007Sroberto 4698182007Sroberto if (disable_dynamic_updates) { 4699182007Sroberto /* 4700285612Sdelphij * discard ourselves if we are not needed any more 4701182007Sroberto * usually happens when running unprivileged 4702182007Sroberto */ 4703182007Sroberto remove_asyncio_reader(reader); 4704182007Sroberto delete_asyncio_reader(reader); 4705182007Sroberto return; 4706182007Sroberto } 4707182007Sroberto 4708182007Sroberto cnt = read(reader->fd, buffer, sizeof(buffer)); 4709285612Sdelphij 4710182007Sroberto if (cnt < 0) { 4711289997Sglebius if (errno == ENOBUFS) { 4712289997Sglebius msyslog(LOG_ERR, 4713289997Sglebius "routing socket reports: %m"); 4714289997Sglebius } else { 4715289997Sglebius msyslog(LOG_ERR, 4716289997Sglebius "routing socket reports: %m - disabling"); 4717289997Sglebius remove_asyncio_reader(reader); 4718289997Sglebius delete_asyncio_reader(reader); 4719289997Sglebius } 4720182007Sroberto return; 4721182007Sroberto } 4722182007Sroberto 4723182007Sroberto /* 4724182007Sroberto * process routing message 4725182007Sroberto */ 4726285612Sdelphij#ifdef HAVE_RTNETLINK 4727293650Sglebius for (nh = UA_PTR(struct nlmsghdr, buffer); 4728285612Sdelphij NLMSG_OK(nh, cnt); 4729285612Sdelphij nh = NLMSG_NEXT(nh, cnt)) { 4730285612Sdelphij msg_type = nh->nlmsg_type; 4731285612Sdelphij#else 4732285612Sdelphij for (p = buffer; 4733285612Sdelphij (p + sizeof(struct rt_msghdr)) <= (buffer + cnt); 4734285612Sdelphij p += rtm.rtm_msglen) { 4735285612Sdelphij memcpy(&rtm, p, sizeof(rtm)); 4736285612Sdelphij if (rtm.rtm_version != RTM_VERSION) { 4737285612Sdelphij msyslog(LOG_ERR, 4738285612Sdelphij "version mismatch (got %d - expected %d) on routing socket - disabling", 4739285612Sdelphij rtm.rtm_version, RTM_VERSION); 4740285612Sdelphij 4741182007Sroberto remove_asyncio_reader(reader); 4742182007Sroberto delete_asyncio_reader(reader); 4743182007Sroberto return; 4744182007Sroberto } 4745285612Sdelphij msg_type = rtm.rtm_type; 4746285612Sdelphij#endif 4747285612Sdelphij switch (msg_type) { 4748182007Sroberto#ifdef RTM_NEWADDR 4749182007Sroberto case RTM_NEWADDR: 4750182007Sroberto#endif 4751182007Sroberto#ifdef RTM_DELADDR 4752182007Sroberto case RTM_DELADDR: 4753182007Sroberto#endif 4754182007Sroberto#ifdef RTM_ADD 4755182007Sroberto case RTM_ADD: 4756182007Sroberto#endif 4757182007Sroberto#ifdef RTM_DELETE 4758182007Sroberto case RTM_DELETE: 4759182007Sroberto#endif 4760182007Sroberto#ifdef RTM_REDIRECT 4761182007Sroberto case RTM_REDIRECT: 4762182007Sroberto#endif 4763182007Sroberto#ifdef RTM_CHANGE 4764182007Sroberto case RTM_CHANGE: 4765182007Sroberto#endif 4766182007Sroberto#ifdef RTM_LOSING 4767182007Sroberto case RTM_LOSING: 4768182007Sroberto#endif 4769182007Sroberto#ifdef RTM_IFINFO 4770182007Sroberto case RTM_IFINFO: 4771182007Sroberto#endif 4772182007Sroberto#ifdef RTM_IFANNOUNCE 4773182007Sroberto case RTM_IFANNOUNCE: 4774182007Sroberto#endif 4775285612Sdelphij#ifdef RTM_NEWLINK 4776285612Sdelphij case RTM_NEWLINK: 4777285612Sdelphij#endif 4778285612Sdelphij#ifdef RTM_DELLINK 4779285612Sdelphij case RTM_DELLINK: 4780285612Sdelphij#endif 4781285612Sdelphij#ifdef RTM_NEWROUTE 4782285612Sdelphij case RTM_NEWROUTE: 4783285612Sdelphij#endif 4784285612Sdelphij#ifdef RTM_DELROUTE 4785285612Sdelphij case RTM_DELROUTE: 4786285612Sdelphij#endif 4787182007Sroberto /* 4788285612Sdelphij * we are keen on new and deleted addresses and 4789285612Sdelphij * if an interface goes up and down or routing 4790285612Sdelphij * changes 4791182007Sroberto */ 4792285612Sdelphij DPRINTF(3, ("routing message op = %d: scheduling interface update\n", 4793285612Sdelphij msg_type)); 4794182007Sroberto timer_interfacetimeout(current_time + UPDATE_GRACE); 4795182007Sroberto break; 4796285612Sdelphij#ifdef HAVE_RTNETLINK 4797285612Sdelphij case NLMSG_DONE: 4798285612Sdelphij /* end of multipart message */ 4799285612Sdelphij return; 4800285612Sdelphij#endif 4801182007Sroberto default: 4802182007Sroberto /* 4803182007Sroberto * the rest doesn't bother us. 4804182007Sroberto */ 4805285612Sdelphij DPRINTF(4, ("routing message op = %d: ignored\n", 4806285612Sdelphij msg_type)); 4807182007Sroberto break; 4808182007Sroberto } 4809182007Sroberto } 4810182007Sroberto} 4811182007Sroberto 4812182007Sroberto/* 4813182007Sroberto * set up routing notifications 4814182007Sroberto */ 4815182007Srobertostatic void 4816182007Srobertoinit_async_notifications() 4817182007Sroberto{ 4818182007Sroberto struct asyncio_reader *reader; 4819285612Sdelphij#ifdef HAVE_RTNETLINK 4820285612Sdelphij int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 4821285612Sdelphij struct sockaddr_nl sa; 4822285612Sdelphij#else 4823182007Sroberto int fd = socket(PF_ROUTE, SOCK_RAW, 0); 4824285612Sdelphij#endif 4825285612Sdelphij if (fd < 0) { 4826285612Sdelphij msyslog(LOG_ERR, 4827285612Sdelphij "unable to open routing socket (%m) - using polled interface update"); 4828285612Sdelphij return; 4829285612Sdelphij } 4830285612Sdelphij 4831285612Sdelphij fd = move_fd(fd); 4832285612Sdelphij#ifdef HAVE_RTNETLINK 4833285612Sdelphij ZERO(sa); 4834285612Sdelphij sa.nl_family = PF_NETLINK; 4835285612Sdelphij sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR 4836285612Sdelphij | RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_ROUTE 4837285612Sdelphij | RTMGRP_IPV4_MROUTE | RTMGRP_IPV6_ROUTE 4838285612Sdelphij | RTMGRP_IPV6_MROUTE; 4839285612Sdelphij if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 4840285612Sdelphij msyslog(LOG_ERR, 4841285612Sdelphij "bind failed on routing socket (%m) - using polled interface update"); 4842285612Sdelphij return; 4843285612Sdelphij } 4844285612Sdelphij#endif 4845285612Sdelphij make_socket_nonblocking(fd); 4846182007Sroberto#if defined(HAVE_SIGNALED_IO) 4847285612Sdelphij init_socket_sig(fd); 4848182007Sroberto#endif /* HAVE_SIGNALED_IO */ 4849182007Sroberto 4850285612Sdelphij reader = new_asyncio_reader(); 4851285612Sdelphij 4852285612Sdelphij reader->fd = fd; 4853285612Sdelphij reader->receiver = process_routing_msgs; 4854285612Sdelphij 4855285612Sdelphij add_asyncio_reader(reader, FD_TYPE_SOCKET); 4856285612Sdelphij msyslog(LOG_INFO, 4857285612Sdelphij "Listening on routing socket on fd #%d for interface updates", 4858285612Sdelphij fd); 4859182007Sroberto} 4860182007Sroberto#else 4861285612Sdelphij/* HAS_ROUTING_SOCKET not defined */ 4862182007Srobertostatic void 4863285612Sdelphijinit_async_notifications(void) 4864182007Sroberto{ 4865182007Sroberto} 4866182007Sroberto#endif 4867285612Sdelphij 4868