xref: /netbsd/external/bsd/ntp/dist/ntpd/ntp_io.c (revision e03b00c8)
1*e03b00c8Schristos /*	$NetBSD: ntp_io.c,v 1.32 2022/10/09 21:41:03 christos Exp $	*/
2abb0f93cSkardel 
3abb0f93cSkardel /*
4abb0f93cSkardel  * ntp_io.c - input/output routines for ntpd.	The socket-opening code
5abb0f93cSkardel  *		   was shamelessly stolen from ntpd.
6abb0f93cSkardel  */
7abb0f93cSkardel 
8abb0f93cSkardel #ifdef HAVE_CONFIG_H
9abb0f93cSkardel # include <config.h>
10abb0f93cSkardel #endif
11abb0f93cSkardel 
12abb0f93cSkardel #include <stdio.h>
13abb0f93cSkardel #include <signal.h>
14ad131110Schristos #ifdef HAVE_FNMATCH_H
15ad131110Schristos # include <fnmatch.h>
16ad131110Schristos # if !defined(FNM_CASEFOLD) && defined(FNM_IGNORECASE)
17ad131110Schristos #  define FNM_CASEFOLD FNM_IGNORECASE
18ad131110Schristos # endif
19ad131110Schristos #endif
20abb0f93cSkardel #ifdef HAVE_SYS_PARAM_H
21abb0f93cSkardel # include <sys/param.h>
22abb0f93cSkardel #endif
23abb0f93cSkardel #ifdef HAVE_SYS_IOCTL_H
24abb0f93cSkardel # include <sys/ioctl.h>
25abb0f93cSkardel #endif
26abb0f93cSkardel #ifdef HAVE_SYS_SOCKIO_H	/* UXPV: SIOC* #defines (Frank Vance <fvance@waii.com>) */
27abb0f93cSkardel # include <sys/sockio.h>
28abb0f93cSkardel #endif
29abb0f93cSkardel #ifdef HAVE_SYS_UIO_H
30abb0f93cSkardel # include <sys/uio.h>
31abb0f93cSkardel #endif
32abb0f93cSkardel 
33abb0f93cSkardel #include "ntp_machine.h"
34abb0f93cSkardel #include "ntpd.h"
35abb0f93cSkardel #include "ntp_io.h"
36abb0f93cSkardel #include "iosignal.h"
37abb0f93cSkardel #include "ntp_lists.h"
38abb0f93cSkardel #include "ntp_refclock.h"
39abb0f93cSkardel #include "ntp_stdlib.h"
40b3d6264cSchristos #include "ntp_worker.h"
41abb0f93cSkardel #include "ntp_request.h"
42abb0f93cSkardel #include "ntp_assert.h"
43b3d6264cSchristos #include "timevalops.h"
44b3d6264cSchristos #include "timespecops.h"
45abb0f93cSkardel #include "ntpd-opts.h"
46bd25f4c4Schristos #include "safecast.h"
47abb0f93cSkardel 
48abb0f93cSkardel /* Don't include ISC's version of IPv6 variables and structures */
49abb0f93cSkardel #define ISC_IPV6_H 1
50abb0f93cSkardel #include <isc/mem.h>
51abb0f93cSkardel #include <isc/interfaceiter.h>
52abb0f93cSkardel #include <isc/netaddr.h>
53abb0f93cSkardel #include <isc/result.h>
54abb0f93cSkardel #include <isc/sockaddr.h>
55abb0f93cSkardel 
56abb0f93cSkardel #ifdef SIM
57abb0f93cSkardel #include "ntpsim.h"
58abb0f93cSkardel #endif
59abb0f93cSkardel 
60abb0f93cSkardel #ifdef HAS_ROUTING_SOCKET
61abb0f93cSkardel # include <net/route.h>
62abb0f93cSkardel # ifdef HAVE_RTNETLINK
63abb0f93cSkardel #  include <linux/rtnetlink.h>
64abb0f93cSkardel # endif
65abb0f93cSkardel #endif
66abb0f93cSkardel 
67abb0f93cSkardel /*
68abb0f93cSkardel  * setsockopt does not always have the same arg declaration
69abb0f93cSkardel  * across all platforms. If it's not defined we make it empty
70abb0f93cSkardel  */
71abb0f93cSkardel 
72abb0f93cSkardel #ifndef SETSOCKOPT_ARG_CAST
73abb0f93cSkardel #define SETSOCKOPT_ARG_CAST
74abb0f93cSkardel #endif
75abb0f93cSkardel 
76abb0f93cSkardel extern int listen_to_virtual_ips;
77abb0f93cSkardel 
784e3b3909Schristos #ifndef IPTOS_DSCP_EF
794e3b3909Schristos #define IPTOS_DSCP_EF 0xb8
804e3b3909Schristos #endif
814e3b3909Schristos int qos = IPTOS_DSCP_EF;	/* QoS RFC3246 */
824e3b3909Schristos 
834e3b3909Schristos #ifdef LEAP_SMEAR
844e3b3909Schristos /* TODO burnicki: This should be moved to ntp_timer.c, but if we do so
854e3b3909Schristos  * we get a linker error. Since we're running out of time before the leap
864e3b3909Schristos  * second occurs, we let it here where it just works.
874e3b3909Schristos  */
884e3b3909Schristos int leap_smear_intv;
894e3b3909Schristos #endif
904e3b3909Schristos 
91abb0f93cSkardel /*
92abb0f93cSkardel  * NIC rule entry
93abb0f93cSkardel  */
94abb0f93cSkardel typedef struct nic_rule_tag nic_rule;
95abb0f93cSkardel 
96abb0f93cSkardel struct nic_rule_tag {
97abb0f93cSkardel 	nic_rule *	next;
98abb0f93cSkardel 	nic_rule_action	action;
99abb0f93cSkardel 	nic_rule_match	match_type;
100abb0f93cSkardel 	char *		if_name;
10145530cf1Skardel 	sockaddr_u	addr;
102abb0f93cSkardel 	int		prefixlen;
103abb0f93cSkardel };
104abb0f93cSkardel 
105abb0f93cSkardel /*
106abb0f93cSkardel  * NIC rule listhead.  Entries are added at the head so that the first
107abb0f93cSkardel  * match in the list is the last matching rule specified.
108abb0f93cSkardel  */
109abb0f93cSkardel nic_rule *nic_rule_list;
110abb0f93cSkardel 
111abb0f93cSkardel 
112b3d6264cSchristos #if defined(SO_BINTIME) && defined(SCM_BINTIME) && defined(CMSG_FIRSTHDR)
113b3d6264cSchristos #  define HAVE_PACKET_TIMESTAMP
114b3d6264cSchristos #  define HAVE_BINTIME
115b3d6264cSchristos #  ifdef BINTIME_CTLMSGBUF_SIZE
116b3d6264cSchristos #   define CMSG_BUFSIZE BINTIME_CTLMSGBUF_SIZE
117b3d6264cSchristos #  else
118b3d6264cSchristos #   define CMSG_BUFSIZE  1536 /* moderate default */
119b3d6264cSchristos #  endif
120b3d6264cSchristos #elif defined(SO_TIMESTAMPNS) && defined(SCM_TIMESTAMPNS) && defined(CMSG_FIRSTHDR)
121b3d6264cSchristos #  define HAVE_PACKET_TIMESTAMP
122b3d6264cSchristos #  define HAVE_TIMESTAMPNS
123b3d6264cSchristos #  ifdef TIMESTAMPNS_CTLMSGBUF_SIZE
124b3d6264cSchristos #   define CMSG_BUFSIZE TIMESTAMPNS_CTLMSGBUF_SIZE
125b3d6264cSchristos #  else
126b3d6264cSchristos #   define CMSG_BUFSIZE  1536 /* moderate default */
127b3d6264cSchristos #  endif
128b3d6264cSchristos #elif defined(SO_TIMESTAMP) && defined(SCM_TIMESTAMP) && defined(CMSG_FIRSTHDR)
129b3d6264cSchristos #  define HAVE_PACKET_TIMESTAMP
130abb0f93cSkardel #  define HAVE_TIMESTAMP
131b3d6264cSchristos #  ifdef TIMESTAMP_CTLMSGBUF_SIZE
132b3d6264cSchristos #   define CMSG_BUFSIZE TIMESTAMP_CTLMSGBUF_SIZE
133b3d6264cSchristos #  else
134b3d6264cSchristos #   define CMSG_BUFSIZE  1536 /* moderate default */
135abb0f93cSkardel #  endif
136abb0f93cSkardel #else
137abb0f93cSkardel /* fill in for old/other timestamp interfaces */
138abb0f93cSkardel #endif
139abb0f93cSkardel 
140abb0f93cSkardel #if defined(SYS_WINNT)
141b3d6264cSchristos #include "win32_io.h"
142abb0f93cSkardel #include <isc/win32os.h>
143b3d6264cSchristos #endif
144abb0f93cSkardel 
145abb0f93cSkardel /*
146abb0f93cSkardel  * We do asynchronous input using the SIGIO facility.  A number of
147abb0f93cSkardel  * recvbuf buffers are preallocated for input.	In the signal
148abb0f93cSkardel  * handler we poll to see which sockets are ready and read the
149abb0f93cSkardel  * packets from them into the recvbuf's along with a time stamp and
150abb0f93cSkardel  * an indication of the source host and the interface it was received
151abb0f93cSkardel  * through.  This allows us to get as accurate receive time stamps
152abb0f93cSkardel  * as possible independent of other processing going on.
153abb0f93cSkardel  *
154abb0f93cSkardel  * We watch the number of recvbufs available to the signal handler
155abb0f93cSkardel  * and allocate more when this number drops below the low water
156abb0f93cSkardel  * mark.  If the signal handler should run out of buffers in the
157abb0f93cSkardel  * interim it will drop incoming frames, the idea being that it is
158abb0f93cSkardel  * better to drop a packet than to be inaccurate.
159abb0f93cSkardel  */
160abb0f93cSkardel 
161abb0f93cSkardel 
162abb0f93cSkardel /*
163abb0f93cSkardel  * Other statistics of possible interest
164abb0f93cSkardel  */
165abb0f93cSkardel volatile u_long packets_dropped;	/* total number of packets dropped on reception */
166abb0f93cSkardel volatile u_long packets_ignored;	/* packets received on wild card interface */
167abb0f93cSkardel volatile u_long packets_received;	/* total number of packets received */
168abb0f93cSkardel 	 u_long packets_sent;		/* total number of packets sent */
169abb0f93cSkardel 	 u_long packets_notsent;	/* total number of packets which couldn't be sent */
170abb0f93cSkardel 
171abb0f93cSkardel volatile u_long handler_calls;	/* number of calls to interrupt handler */
172abb0f93cSkardel volatile u_long handler_pkts;	/* number of pkts received by handler */
173abb0f93cSkardel u_long io_timereset;		/* time counters were reset */
174abb0f93cSkardel 
175abb0f93cSkardel /*
176abb0f93cSkardel  * Interface stuff
177abb0f93cSkardel  */
17845530cf1Skardel endpt *	any_interface;		/* wildcard ipv4 interface */
17945530cf1Skardel endpt *	any6_interface;		/* wildcard ipv6 interface */
18045530cf1Skardel endpt *	loopback_interface;	/* loopback ipv4 interface */
181abb0f93cSkardel 
1829034ec65Schristos static isc_boolean_t broadcast_client_enabled;	/* is broadcast client enabled */
183b3d6264cSchristos u_int sys_ifnum;			/* next .ifnum to assign */
184abb0f93cSkardel int ninterfaces;			/* Total number of interfaces */
185abb0f93cSkardel 
186abb0f93cSkardel int disable_dynamic_updates;		/* scan interfaces once only */
187abb0f93cSkardel 
188abb0f93cSkardel #ifdef REFCLOCK
189abb0f93cSkardel /*
190abb0f93cSkardel  * Refclock stuff.	We keep a chain of structures with data concerning
191abb0f93cSkardel  * the guys we are doing I/O for.
192abb0f93cSkardel  */
193abb0f93cSkardel static	struct refclockio *refio;
194abb0f93cSkardel #endif /* REFCLOCK */
195abb0f93cSkardel 
196abb0f93cSkardel /*
197abb0f93cSkardel  * File descriptor masks etc. for call to select
198b3d6264cSchristos  * Not needed for I/O Completion Ports or anything outside this file
199abb0f93cSkardel  */
200b3d6264cSchristos static fd_set activefds;
201b3d6264cSchristos static int maxactivefd;
202b3d6264cSchristos 
203abb0f93cSkardel /*
204abb0f93cSkardel  * bit alternating value to detect verified interfaces during an update cycle
205abb0f93cSkardel  */
206abb0f93cSkardel static  u_short		sys_interphase = 0;
207abb0f93cSkardel 
20845530cf1Skardel static endpt *	new_interface(endpt *);
20945530cf1Skardel static void	add_interface(endpt *);
21045530cf1Skardel static int	update_interfaces(u_short, interface_receiver_t,
21145530cf1Skardel 				  void *);
21245530cf1Skardel static void	remove_interface(endpt *);
21345530cf1Skardel static endpt *	create_interface(u_short, endpt *);
214abb0f93cSkardel 
21545530cf1Skardel static int	is_wildcard_addr	(const sockaddr_u *);
216abb0f93cSkardel 
217abb0f93cSkardel /*
218abb0f93cSkardel  * Multicast functions
219abb0f93cSkardel  */
220abb0f93cSkardel static	isc_boolean_t	addr_ismulticast	(sockaddr_u *);
22145530cf1Skardel static	isc_boolean_t	is_anycast		(sockaddr_u *,
22245530cf1Skardel 						 const char *);
22345530cf1Skardel 
224abb0f93cSkardel /*
225abb0f93cSkardel  * Not all platforms support multicast
226abb0f93cSkardel  */
227abb0f93cSkardel #ifdef MCAST
22845530cf1Skardel static	isc_boolean_t	socket_multicast_enable	(endpt *, sockaddr_u *);
22945530cf1Skardel static	isc_boolean_t	socket_multicast_disable(endpt *, sockaddr_u *);
230abb0f93cSkardel #endif
231abb0f93cSkardel 
232abb0f93cSkardel #ifdef DEBUG
23345530cf1Skardel static void interface_dump	(const endpt *);
23445530cf1Skardel static void sockaddr_dump	(const sockaddr_u *);
235f40817b7Skardel static void print_interface	(const endpt *, const char *, const char *);
236abb0f93cSkardel #define DPRINT_INTERFACE(level, args) do { if (debug >= (level)) { print_interface args; } } while (0)
237abb0f93cSkardel #else
238abb0f93cSkardel #define DPRINT_INTERFACE(level, args) do {} while (0)
239abb0f93cSkardel #endif
240abb0f93cSkardel 
241abb0f93cSkardel typedef struct vsock vsock_t;
242abb0f93cSkardel enum desc_type { FD_TYPE_SOCKET, FD_TYPE_FILE };
243abb0f93cSkardel 
244abb0f93cSkardel struct vsock {
245abb0f93cSkardel 	vsock_t	*	link;
246abb0f93cSkardel 	SOCKET		fd;
247abb0f93cSkardel 	enum desc_type	type;
248abb0f93cSkardel };
249abb0f93cSkardel 
250abb0f93cSkardel vsock_t	*fd_list;
251abb0f93cSkardel 
252abb0f93cSkardel #if !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET)
253abb0f93cSkardel /*
254abb0f93cSkardel  * async notification processing (e. g. routing sockets)
255abb0f93cSkardel  */
256abb0f93cSkardel /*
257abb0f93cSkardel  * support for receiving data on fd that is not a refclock or a socket
258abb0f93cSkardel  * like e. g. routing sockets
259abb0f93cSkardel  */
260abb0f93cSkardel struct asyncio_reader {
261abb0f93cSkardel 	struct asyncio_reader *link;		    /* the list this is being kept in */
262abb0f93cSkardel 	SOCKET fd;				    /* fd to be read */
263abb0f93cSkardel 	void  *data;				    /* possibly local data */
264abb0f93cSkardel 	void (*receiver)(struct asyncio_reader *);  /* input handler */
265abb0f93cSkardel };
266abb0f93cSkardel 
267abb0f93cSkardel struct asyncio_reader *asyncio_reader_list;
268abb0f93cSkardel 
269abb0f93cSkardel static void delete_asyncio_reader (struct asyncio_reader *);
270abb0f93cSkardel static struct asyncio_reader *new_asyncio_reader (void);
271abb0f93cSkardel static void add_asyncio_reader (struct asyncio_reader *, enum desc_type);
272abb0f93cSkardel static void remove_asyncio_reader (struct asyncio_reader *);
273abb0f93cSkardel 
274abb0f93cSkardel #endif /* !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) */
275abb0f93cSkardel 
276abb0f93cSkardel static void init_async_notifications (void);
277abb0f93cSkardel 
27845530cf1Skardel static	int	addr_eqprefix	(const sockaddr_u *, const sockaddr_u *,
27945530cf1Skardel 				 int);
28045530cf1Skardel static int	addr_samesubnet	(const sockaddr_u *, const sockaddr_u *,
28145530cf1Skardel 				 const sockaddr_u *, const sockaddr_u *);
282abb0f93cSkardel static	int	create_sockets	(u_short);
28345530cf1Skardel static	SOCKET	open_socket	(sockaddr_u *, int, int, endpt *);
284abb0f93cSkardel static	void	set_reuseaddr	(int);
285abb0f93cSkardel static	isc_boolean_t	socket_broadcast_enable	 (struct interface *, SOCKET, sockaddr_u *);
286335f7552Schristos 
287335f7552Schristos #if !defined(HAVE_IO_COMPLETION_PORT) && !defined(HAVE_SIGNALED_IO)
288335f7552Schristos static	char *	fdbits		(int, const fd_set *);
289335f7552Schristos #endif
290ad131110Schristos #ifdef  OS_MISSES_SPECIFIC_ROUTE_UPDATES
291abb0f93cSkardel static	isc_boolean_t	socket_broadcast_disable (struct interface *, sockaddr_u *);
292ad131110Schristos #endif
293abb0f93cSkardel 
294abb0f93cSkardel typedef struct remaddr remaddr_t;
295abb0f93cSkardel 
296abb0f93cSkardel struct remaddr {
297abb0f93cSkardel 	remaddr_t *		link;
298abb0f93cSkardel 	sockaddr_u		addr;
29945530cf1Skardel 	endpt *			ep;
300abb0f93cSkardel };
301abb0f93cSkardel 
302abb0f93cSkardel remaddr_t *	remoteaddr_list;
30345530cf1Skardel endpt *		ep_list;	/* complete endpt list */
30445530cf1Skardel endpt *		mc4_list;	/* IPv4 mcast-capable unicast endpts */
30545530cf1Skardel endpt *		mc6_list;	/* IPv6 mcast-capable unicast endpts */
306abb0f93cSkardel 
30745530cf1Skardel static endpt *	wildipv4;
30845530cf1Skardel static endpt *	wildipv6;
309abb0f93cSkardel 
310b3d6264cSchristos #ifdef SYS_WINNT
311b3d6264cSchristos int accept_wildcard_if_for_winnt;
312b3d6264cSchristos #else
313b3d6264cSchristos const int accept_wildcard_if_for_winnt = FALSE;
314b3d6264cSchristos #endif
315b3d6264cSchristos 
31645530cf1Skardel static void	add_fd_to_list		(SOCKET, enum desc_type);
31745530cf1Skardel static endpt *	find_addr_in_list	(sockaddr_u *);
31845530cf1Skardel static endpt *	find_flagged_addr_in_list(sockaddr_u *, u_int32);
319abb0f93cSkardel static void	delete_addr_from_list	(sockaddr_u *);
32045530cf1Skardel static void	delete_interface_from_list(endpt *);
321abb0f93cSkardel static void	close_and_delete_fd_from_list(SOCKET);
32245530cf1Skardel static void	add_addr_to_list	(sockaddr_u *, endpt *);
323abb0f93cSkardel static void	create_wildcards	(u_short);
32445530cf1Skardel static endpt *	findlocalinterface	(sockaddr_u *, int, int);
32545530cf1Skardel static endpt *	findclosestinterface	(sockaddr_u *, int);
326abb0f93cSkardel #ifdef DEBUG
327abb0f93cSkardel static const char *	action_text	(nic_rule_action);
328abb0f93cSkardel #endif
32945530cf1Skardel static nic_rule_action	interface_action(char *, sockaddr_u *, u_int32);
330abb0f93cSkardel static void		convert_isc_if	(isc_interface_t *,
33145530cf1Skardel 					 endpt *, u_short);
33245530cf1Skardel static void		calc_addr_distance(sockaddr_u *,
33345530cf1Skardel 					   const sockaddr_u *,
33445530cf1Skardel 					   const sockaddr_u *);
33545530cf1Skardel static int		cmp_addr_distance(const sockaddr_u *,
33645530cf1Skardel 					  const sockaddr_u *);
337abb0f93cSkardel 
338abb0f93cSkardel /*
339abb0f93cSkardel  * Routines to read the ntp packets
340abb0f93cSkardel  */
341abb0f93cSkardel #if !defined(HAVE_IO_COMPLETION_PORT)
342abb0f93cSkardel static inline int	read_network_packet	(SOCKET, struct interface *, l_fp);
343b3d6264cSchristos static void		ntpd_addremove_io_fd	(int, int, int);
344335f7552Schristos static void 		input_handler_scan	(const l_fp*, const fd_set*);
345335f7552Schristos static int/*BOOL*/	sanitize_fdset		(int errc);
346b3d6264cSchristos #ifdef REFCLOCK
347abb0f93cSkardel static inline int	read_refclock_packet	(SOCKET, struct refclockio *, l_fp);
348abb0f93cSkardel #endif
349335f7552Schristos #ifdef HAVE_SIGNALED_IO
350335f7552Schristos static void 		input_handler		(l_fp*);
351b3d6264cSchristos #endif
352335f7552Schristos #endif
353abb0f93cSkardel 
354b3d6264cSchristos 
355b3d6264cSchristos #ifndef HAVE_IO_COMPLETION_PORT
356abb0f93cSkardel void
maintain_activefds(int fd,int closing)357b3d6264cSchristos maintain_activefds(
358b3d6264cSchristos 	int fd,
359b3d6264cSchristos 	int closing
360abb0f93cSkardel 	)
361abb0f93cSkardel {
362b3d6264cSchristos 	int i;
363abb0f93cSkardel 
364b3d6264cSchristos 	if (fd < 0 || fd >= FD_SETSIZE) {
365abb0f93cSkardel 		msyslog(LOG_ERR,
366b3d6264cSchristos 			"Too many sockets in use, FD_SETSIZE %d exceeded by fd %d",
367b3d6264cSchristos 			FD_SETSIZE, fd);
368b3d6264cSchristos 		exit(1);
369abb0f93cSkardel 	}
370abb0f93cSkardel 
371b3d6264cSchristos 	if (!closing) {
372b3d6264cSchristos 		FD_SET(fd, &activefds);
373b3d6264cSchristos 		maxactivefd = max(fd, maxactivefd);
374abb0f93cSkardel 	} else {
375b3d6264cSchristos 		FD_CLR(fd, &activefds);
376b3d6264cSchristos 		if (maxactivefd && fd == maxactivefd) {
377b3d6264cSchristos 			for (i = maxactivefd - 1; i >= 0; i--)
378b3d6264cSchristos 				if (FD_ISSET(i, &activefds)) {
379b3d6264cSchristos 					maxactivefd = i;
380b3d6264cSchristos 					break;
381abb0f93cSkardel 				}
38209f14f80Schristos 			INSIST(fd != maxactivefd);
383abb0f93cSkardel 		}
384b3d6264cSchristos 	}
385b3d6264cSchristos }
386b3d6264cSchristos #endif	/* !HAVE_IO_COMPLETION_PORT */
387b3d6264cSchristos 
388abb0f93cSkardel 
389abb0f93cSkardel #ifdef DEBUG_TIMING
390abb0f93cSkardel /*
391abb0f93cSkardel  * collect timing information for various processing
392b3d6264cSchristos  * paths. currently we only pass them on to the file
393abb0f93cSkardel  * for later processing. this could also do histogram
394abb0f93cSkardel  * based analysis in other to reduce the load (and skew)
395abb0f93cSkardel  * dur to the file output
396abb0f93cSkardel  */
397abb0f93cSkardel void
collect_timing(struct recvbuf * rb,const char * tag,int count,l_fp * dts)398abb0f93cSkardel collect_timing(struct recvbuf *rb, const char *tag, int count, l_fp *dts)
399abb0f93cSkardel {
400abb0f93cSkardel 	char buf[256];
401abb0f93cSkardel 
402abb0f93cSkardel 	snprintf(buf, sizeof(buf), "%s %d %s %s",
403abb0f93cSkardel 		 (rb != NULL)
404abb0f93cSkardel 		     ? ((rb->dstadr != NULL)
405abb0f93cSkardel 			    ? stoa(&rb->recv_srcadr)
406abb0f93cSkardel 			    : "-REFCLOCK-")
407abb0f93cSkardel 		     : "-",
408abb0f93cSkardel 		 count, lfptoa(dts, 9), tag);
409abb0f93cSkardel 	record_timing_stats(buf);
410abb0f93cSkardel }
411abb0f93cSkardel #endif
412abb0f93cSkardel 
413abb0f93cSkardel /*
414abb0f93cSkardel  * About dynamic interfaces, sockets, reception and more...
415abb0f93cSkardel  *
416abb0f93cSkardel  * the code solves following tasks:
417abb0f93cSkardel  *
418abb0f93cSkardel  *   - keep a current list of active interfaces in order
419abb0f93cSkardel  *     to bind to to the interface address on NTP_PORT so that
420abb0f93cSkardel  *     all wild and specific bindings for NTP_PORT are taken by ntpd
421abb0f93cSkardel  *     to avoid other daemons messing with the time or sockets.
422abb0f93cSkardel  *   - all interfaces keep a list of peers that are referencing
423abb0f93cSkardel  *     the interface in order to quickly re-assign the peers to
424abb0f93cSkardel  *     new interface in case an interface is deleted (=> gone from system or
425abb0f93cSkardel  *     down)
426abb0f93cSkardel  *   - have a preconfigured socket ready with the right local address
427abb0f93cSkardel  *     for transmission and reception
428abb0f93cSkardel  *   - have an address list for all destination addresses used within ntpd
429abb0f93cSkardel  *     to find the "right" preconfigured socket.
430abb0f93cSkardel  *   - facilitate updating the internal interface list with respect to
431abb0f93cSkardel  *     the current kernel state
432abb0f93cSkardel  *
433abb0f93cSkardel  * special issues:
434abb0f93cSkardel  *
435abb0f93cSkardel  *   - mapping of multicast addresses to the interface affected is not always
436abb0f93cSkardel  *     one to one - especially on hosts with multiple interfaces
437abb0f93cSkardel  *     the code here currently allocates a separate interface entry for those
438abb0f93cSkardel  *     multicast addresses
439abb0f93cSkardel  *     iff it is able to bind to a *new* socket with the multicast address (flags |= MCASTIF)
440abb0f93cSkardel  *     in case of failure the multicast address is bound to an existing interface.
441abb0f93cSkardel  *   - on some systems it is perfectly legal to assign the same address to
442abb0f93cSkardel  *     multiple interfaces. Therefore this code does not keep a list of interfaces
443abb0f93cSkardel  *     but a list of interfaces that represent a unique address as determined by the kernel
444abb0f93cSkardel  *     by the procedure in findlocalinterface. Thus it is perfectly legal to see only
445abb0f93cSkardel  *     one representative of a group of real interfaces if they share the same address.
446abb0f93cSkardel  *
447abb0f93cSkardel  * Frank Kardel 20050910
448abb0f93cSkardel  */
449abb0f93cSkardel 
450abb0f93cSkardel /*
451b3d6264cSchristos  * init_io - initialize I/O module.
452abb0f93cSkardel  */
453abb0f93cSkardel void
init_io(void)454abb0f93cSkardel init_io(void)
455abb0f93cSkardel {
456b3d6264cSchristos 	/* Init buffer free list and stat counters */
457abb0f93cSkardel 	init_recvbuff(RECV_INIT);
458dd91765eSroy #ifdef SO_RERROR
459dd91765eSroy 	/* route(4) overflow can be observed */
460dd91765eSroy 	interface_interval = 0;
461dd91765eSroy #else
462b3d6264cSchristos 	/* update interface every 5 minutes as default */
463b3d6264cSchristos 	interface_interval = 300;
464dd91765eSroy #endif
465b3d6264cSchristos 
466b3d6264cSchristos #ifdef WORK_PIPE
467b3d6264cSchristos 	addremove_io_fd = &ntpd_addremove_io_fd;
468b3d6264cSchristos #endif
469abb0f93cSkardel 
470335f7552Schristos #if defined(SYS_WINNT)
471abb0f93cSkardel 	init_io_completion_port();
472335f7552Schristos #elif defined(HAVE_SIGNALED_IO)
473b3d6264cSchristos 	(void) set_signal(input_handler);
474abb0f93cSkardel #endif
475abb0f93cSkardel }
476abb0f93cSkardel 
477abb0f93cSkardel 
478b3d6264cSchristos static void
ntpd_addremove_io_fd(int fd,int is_pipe,int remove_it)479b3d6264cSchristos ntpd_addremove_io_fd(
480b3d6264cSchristos 	int	fd,
481b3d6264cSchristos 	int	is_pipe,
482b3d6264cSchristos 	int	remove_it
483b3d6264cSchristos 	)
484b3d6264cSchristos {
485b3d6264cSchristos 	UNUSED_ARG(is_pipe);
486b3d6264cSchristos 
487b3d6264cSchristos #ifdef HAVE_SIGNALED_IO
488335f7552Schristos 	if (!remove_it)
489b3d6264cSchristos 		init_socket_sig(fd);
490b3d6264cSchristos #endif /* not HAVE_SIGNALED_IO */
491b3d6264cSchristos 
492b3d6264cSchristos 	maintain_activefds(fd, remove_it);
493b3d6264cSchristos }
494b3d6264cSchristos 
495b3d6264cSchristos 
496abb0f93cSkardel /*
497abb0f93cSkardel  * io_open_sockets - call socket creation routine
498abb0f93cSkardel  */
499abb0f93cSkardel void
io_open_sockets(void)500abb0f93cSkardel io_open_sockets(void)
501abb0f93cSkardel {
502abb0f93cSkardel 	static int already_opened;
503abb0f93cSkardel 
504abb0f93cSkardel 	if (already_opened || HAVE_OPT( SAVECONFIGQUIT ))
505abb0f93cSkardel 		return;
506abb0f93cSkardel 
507abb0f93cSkardel 	already_opened = 1;
508abb0f93cSkardel 
509abb0f93cSkardel 	/*
510abb0f93cSkardel 	 * Create the sockets
511abb0f93cSkardel 	 */
512abb0f93cSkardel 	BLOCKIO();
513abb0f93cSkardel 	create_sockets(NTP_PORT);
514abb0f93cSkardel 	UNBLOCKIO();
515abb0f93cSkardel 
516abb0f93cSkardel 	init_async_notifications();
517abb0f93cSkardel 
518abb0f93cSkardel 	DPRINTF(3, ("io_open_sockets: maxactivefd %d\n", maxactivefd));
519abb0f93cSkardel }
520abb0f93cSkardel 
521abb0f93cSkardel 
522abb0f93cSkardel #ifdef DEBUG
523abb0f93cSkardel /*
524abb0f93cSkardel  * function to dump the contents of the interface structure
525abb0f93cSkardel  * for debugging use only.
5261c24ec91Schristos  * We face a dilemma here -- sockets are FDs under POSIX and
5271c24ec91Schristos  * actually HANDLES under Windows. So we use '%lld' as format
5281c24ec91Schristos  * and cast the value to 'long long'; this should not hurt
5291c24ec91Schristos  * with UNIX-like systems and does not truncate values on Win64.
530abb0f93cSkardel  */
531abb0f93cSkardel void
interface_dump(const endpt * itf)53245530cf1Skardel interface_dump(const endpt *itf)
533abb0f93cSkardel {
534abb0f93cSkardel 	printf("Dumping interface: %p\n", itf);
5351c24ec91Schristos 	printf("fd = %lld\n", (long long)itf->fd);
5361c24ec91Schristos 	printf("bfd = %lld\n", (long long)itf->bfd);
537abb0f93cSkardel 	printf("sin = %s,\n", stoa(&itf->sin));
538abb0f93cSkardel 	sockaddr_dump(&itf->sin);
539abb0f93cSkardel 	printf("bcast = %s,\n", stoa(&itf->bcast));
540abb0f93cSkardel 	sockaddr_dump(&itf->bcast);
541abb0f93cSkardel 	printf("mask = %s,\n", stoa(&itf->mask));
542abb0f93cSkardel 	sockaddr_dump(&itf->mask);
543abb0f93cSkardel 	printf("name = %s\n", itf->name);
544abb0f93cSkardel 	printf("flags = 0x%08x\n", itf->flags);
545abb0f93cSkardel 	printf("last_ttl = %d\n", itf->last_ttl);
546abb0f93cSkardel 	printf("addr_refid = %08x\n", itf->addr_refid);
547abb0f93cSkardel 	printf("num_mcast = %d\n", itf->num_mcast);
548abb0f93cSkardel 	printf("received = %ld\n", itf->received);
549abb0f93cSkardel 	printf("sent = %ld\n", itf->sent);
550abb0f93cSkardel 	printf("notsent = %ld\n", itf->notsent);
55145530cf1Skardel 	printf("ifindex = %u\n", itf->ifindex);
552abb0f93cSkardel 	printf("peercnt = %u\n", itf->peercnt);
553abb0f93cSkardel 	printf("phase = %u\n", itf->phase);
554abb0f93cSkardel }
555abb0f93cSkardel 
556abb0f93cSkardel /*
557abb0f93cSkardel  * sockaddr_dump - hex dump the start of a sockaddr_u
558abb0f93cSkardel  */
559abb0f93cSkardel static void
sockaddr_dump(const sockaddr_u * psau)56045530cf1Skardel sockaddr_dump(const sockaddr_u *psau)
561abb0f93cSkardel {
562b3d6264cSchristos 	/* Limit the size of the sockaddr_in6 hex dump */
56345530cf1Skardel 	const int maxsize = min(32, sizeof(psau->sa6));
56445530cf1Skardel 	const u_char *	cp;
565abb0f93cSkardel 	int		i;
566abb0f93cSkardel 
567b3d6264cSchristos 	/* XXX: Should we limit maxsize based on psau->saX.sin_family? */
568b3d6264cSchristos 	cp = (const void *)&psau->sa6;
569abb0f93cSkardel 
57045530cf1Skardel 	for(i = 0; i < maxsize; i++) {
571abb0f93cSkardel 		printf("%02x", *cp++);
572abb0f93cSkardel 		if (!((i + 1) % 4))
573abb0f93cSkardel 			printf(" ");
574abb0f93cSkardel 	}
575abb0f93cSkardel 	printf("\n");
576abb0f93cSkardel }
577abb0f93cSkardel 
578abb0f93cSkardel /*
579abb0f93cSkardel  * print_interface - helper to output debug information
580abb0f93cSkardel  */
581abb0f93cSkardel static void
print_interface(const endpt * iface,const char * pfx,const char * sfx)582f40817b7Skardel print_interface(const endpt *iface, const char *pfx, const char *sfx)
583abb0f93cSkardel {
5841c24ec91Schristos 	printf("%sinterface #%d: fd=%lld, bfd=%lld, name=%s, flags=0x%x, ifindex=%u, sin=%s",
585abb0f93cSkardel 	       pfx,
586abb0f93cSkardel 	       iface->ifnum,
5871c24ec91Schristos 	       (long long)iface->fd,
5881c24ec91Schristos 	       (long long)iface->bfd,
589abb0f93cSkardel 	       iface->name,
590abb0f93cSkardel 	       iface->flags,
59145530cf1Skardel 	       iface->ifindex,
592abb0f93cSkardel 	       stoa(&iface->sin));
593abb0f93cSkardel 	if (AF_INET == iface->family) {
594abb0f93cSkardel 		if (iface->flags & INT_BROADCAST)
595abb0f93cSkardel 			printf(", bcast=%s", stoa(&iface->bcast));
596abb0f93cSkardel 		printf(", mask=%s", stoa(&iface->mask));
597abb0f93cSkardel 	}
598abb0f93cSkardel 	printf(", %s:%s",
599abb0f93cSkardel 	       (iface->ignore_packets)
600abb0f93cSkardel 		   ? "Disabled"
601abb0f93cSkardel 		   : "Enabled",
602abb0f93cSkardel 	       sfx);
603abb0f93cSkardel 	if (debug > 4)	/* in-depth debugging only */
604abb0f93cSkardel 		interface_dump(iface);
605abb0f93cSkardel }
606abb0f93cSkardel #endif
607abb0f93cSkardel 
608abb0f93cSkardel #if !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET)
609abb0f93cSkardel /*
610abb0f93cSkardel  * create an asyncio_reader structure
611abb0f93cSkardel  */
612abb0f93cSkardel static struct asyncio_reader *
new_asyncio_reader(void)613abb0f93cSkardel new_asyncio_reader(void)
614abb0f93cSkardel {
615abb0f93cSkardel 	struct asyncio_reader *reader;
616abb0f93cSkardel 
617b3d6264cSchristos 	reader = emalloc_zero(sizeof(*reader));
618abb0f93cSkardel 	reader->fd = INVALID_SOCKET;
619b3d6264cSchristos 
620abb0f93cSkardel 	return reader;
621abb0f93cSkardel }
622abb0f93cSkardel 
623abb0f93cSkardel /*
624abb0f93cSkardel  * delete a reader
625abb0f93cSkardel  */
626abb0f93cSkardel static void
delete_asyncio_reader(struct asyncio_reader * reader)627abb0f93cSkardel delete_asyncio_reader(
628abb0f93cSkardel 	struct asyncio_reader *reader
629abb0f93cSkardel 	)
630abb0f93cSkardel {
631abb0f93cSkardel 	free(reader);
632abb0f93cSkardel }
633abb0f93cSkardel 
634abb0f93cSkardel /*
635abb0f93cSkardel  * add asynchio_reader
636abb0f93cSkardel  */
637abb0f93cSkardel static void
add_asyncio_reader(struct asyncio_reader * reader,enum desc_type type)638abb0f93cSkardel add_asyncio_reader(
639abb0f93cSkardel 	struct asyncio_reader *	reader,
640abb0f93cSkardel 	enum desc_type		type)
641abb0f93cSkardel {
642abb0f93cSkardel 	LINK_SLIST(asyncio_reader_list, reader, link);
643abb0f93cSkardel 	add_fd_to_list(reader->fd, type);
644abb0f93cSkardel }
645abb0f93cSkardel 
646abb0f93cSkardel /*
647abb0f93cSkardel  * remove asynchio_reader
648abb0f93cSkardel  */
649abb0f93cSkardel static void
remove_asyncio_reader(struct asyncio_reader * reader)650abb0f93cSkardel remove_asyncio_reader(
651abb0f93cSkardel 	struct asyncio_reader *reader
652abb0f93cSkardel 	)
653abb0f93cSkardel {
654abb0f93cSkardel 	struct asyncio_reader *unlinked;
655abb0f93cSkardel 
656abb0f93cSkardel 	UNLINK_SLIST(unlinked, asyncio_reader_list, reader, link,
657abb0f93cSkardel 	    struct asyncio_reader);
658abb0f93cSkardel 
659abb0f93cSkardel 	if (reader->fd != INVALID_SOCKET)
660abb0f93cSkardel 		close_and_delete_fd_from_list(reader->fd);
661abb0f93cSkardel 
662abb0f93cSkardel 	reader->fd = INVALID_SOCKET;
663abb0f93cSkardel }
664abb0f93cSkardel #endif /* !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) */
665abb0f93cSkardel 
66645530cf1Skardel 
66745530cf1Skardel /* compare two sockaddr prefixes */
66845530cf1Skardel static int
addr_eqprefix(const sockaddr_u * a,const sockaddr_u * b,int prefixlen)66945530cf1Skardel addr_eqprefix(
67045530cf1Skardel 	const sockaddr_u *	a,
67145530cf1Skardel 	const sockaddr_u *	b,
67245530cf1Skardel 	int			prefixlen
67345530cf1Skardel 	)
67445530cf1Skardel {
67545530cf1Skardel 	isc_netaddr_t		isc_a;
67645530cf1Skardel 	isc_netaddr_t		isc_b;
67745530cf1Skardel 	isc_sockaddr_t		isc_sa;
67845530cf1Skardel 
679b3d6264cSchristos 	ZERO(isc_sa);
680b3d6264cSchristos 	memcpy(&isc_sa.type, a, min(sizeof(isc_sa.type), sizeof(*a)));
68145530cf1Skardel 	isc_netaddr_fromsockaddr(&isc_a, &isc_sa);
68245530cf1Skardel 
683b3d6264cSchristos 	ZERO(isc_sa);
684b3d6264cSchristos 	memcpy(&isc_sa.type, b, min(sizeof(isc_sa.type), sizeof(*b)));
68545530cf1Skardel 	isc_netaddr_fromsockaddr(&isc_b, &isc_sa);
68645530cf1Skardel 
68745530cf1Skardel 	return (int)isc_netaddr_eqprefix(&isc_a, &isc_b,
68845530cf1Skardel 					 (u_int)prefixlen);
68945530cf1Skardel }
69045530cf1Skardel 
69145530cf1Skardel 
69245530cf1Skardel static int
addr_samesubnet(const sockaddr_u * a,const sockaddr_u * a_mask,const sockaddr_u * b,const sockaddr_u * b_mask)69345530cf1Skardel addr_samesubnet(
69445530cf1Skardel 	const sockaddr_u *	a,
69545530cf1Skardel 	const sockaddr_u *	a_mask,
69645530cf1Skardel 	const sockaddr_u *	b,
69745530cf1Skardel 	const sockaddr_u *	b_mask
69845530cf1Skardel 	)
69945530cf1Skardel {
70045530cf1Skardel 	const u_int32 *	pa;
70145530cf1Skardel 	const u_int32 *	pa_limit;
70245530cf1Skardel 	const u_int32 *	pb;
70345530cf1Skardel 	const u_int32 *	pm;
70445530cf1Skardel 	size_t		loops;
70545530cf1Skardel 
70609f14f80Schristos 	REQUIRE(AF(a) == AF(a_mask));
70709f14f80Schristos 	REQUIRE(AF(b) == AF(b_mask));
70845530cf1Skardel 	/*
70945530cf1Skardel 	 * With address and mask families verified to match, comparing
71045530cf1Skardel 	 * the masks also validates the address's families match.
71145530cf1Skardel 	 */
71245530cf1Skardel 	if (!SOCK_EQ(a_mask, b_mask))
71345530cf1Skardel 		return FALSE;
71445530cf1Skardel 
71545530cf1Skardel 	if (IS_IPV6(a)) {
71645530cf1Skardel 		loops = sizeof(NSRCADR6(a)) / sizeof(*pa);
71745530cf1Skardel 		pa = (const void *)&NSRCADR6(a);
71845530cf1Skardel 		pb = (const void *)&NSRCADR6(b);
71945530cf1Skardel 		pm = (const void *)&NSRCADR6(a_mask);
72045530cf1Skardel 	} else {
72145530cf1Skardel 		loops = sizeof(NSRCADR(a)) / sizeof(*pa);
72245530cf1Skardel 		pa = (const void *)&NSRCADR(a);
72345530cf1Skardel 		pb = (const void *)&NSRCADR(b);
72445530cf1Skardel 		pm = (const void *)&NSRCADR(a_mask);
72545530cf1Skardel 	}
72645530cf1Skardel 	for (pa_limit = pa + loops; pa < pa_limit; pa++, pb++, pm++)
72745530cf1Skardel 		if ((*pa & *pm) != (*pb & *pm))
72845530cf1Skardel 			return FALSE;
72945530cf1Skardel 
73045530cf1Skardel 	return TRUE;
73145530cf1Skardel }
73245530cf1Skardel 
73345530cf1Skardel 
734abb0f93cSkardel /*
735abb0f93cSkardel  * interface list enumerator - visitor pattern
736abb0f93cSkardel  */
737abb0f93cSkardel void
interface_enumerate(interface_receiver_t receiver,void * data)738abb0f93cSkardel interface_enumerate(
739abb0f93cSkardel 	interface_receiver_t	receiver,
740abb0f93cSkardel 	void *			data
741abb0f93cSkardel 	)
742abb0f93cSkardel {
743abb0f93cSkardel 	interface_info_t ifi;
744abb0f93cSkardel 
745abb0f93cSkardel 	ifi.action = IFS_EXISTS;
74645530cf1Skardel 	for (ifi.ep = ep_list; ifi.ep != NULL; ifi.ep = ifi.ep->elink)
747abb0f93cSkardel 		(*receiver)(data, &ifi);
748abb0f93cSkardel }
749abb0f93cSkardel 
750abb0f93cSkardel /*
751abb0f93cSkardel  * do standard initialization of interface structure
752abb0f93cSkardel  */
753abb0f93cSkardel static void
init_interface(endpt * ep)754abb0f93cSkardel init_interface(
75545530cf1Skardel 	endpt *ep
756abb0f93cSkardel 	)
757abb0f93cSkardel {
758b3d6264cSchristos 	ZERO(*ep);
75945530cf1Skardel 	ep->fd = INVALID_SOCKET;
76045530cf1Skardel 	ep->bfd = INVALID_SOCKET;
76145530cf1Skardel 	ep->phase = sys_interphase;
762abb0f93cSkardel }
763abb0f93cSkardel 
764abb0f93cSkardel 
765abb0f93cSkardel /*
766abb0f93cSkardel  * create new interface structure initialize from
767abb0f93cSkardel  * template structure or via standard initialization
768abb0f93cSkardel  * function
769abb0f93cSkardel  */
770abb0f93cSkardel static struct interface *
new_interface(struct interface * interface)771abb0f93cSkardel new_interface(
772abb0f93cSkardel 	struct interface *interface
773abb0f93cSkardel 	)
774abb0f93cSkardel {
775abb0f93cSkardel 	struct interface *	iface;
776abb0f93cSkardel 
777abb0f93cSkardel 	iface = emalloc(sizeof(*iface));
778abb0f93cSkardel 
779abb0f93cSkardel 	if (NULL == interface)
780abb0f93cSkardel 		init_interface(iface);
781abb0f93cSkardel 	else				/* use the template */
782abb0f93cSkardel 		memcpy(iface, interface, sizeof(*iface));
783abb0f93cSkardel 
784abb0f93cSkardel 	/* count every new instance of an interface in the system */
785abb0f93cSkardel 	iface->ifnum = sys_ifnum++;
786abb0f93cSkardel 	iface->starttime = current_time;
787abb0f93cSkardel 
788335f7552Schristos #   ifdef HAVE_IO_COMPLETION_PORT
789335f7552Schristos 	if (!io_completion_port_add_interface(iface)) {
790335f7552Schristos 		msyslog(LOG_EMERG, "cannot register interface with IO engine -- will exit now");
791335f7552Schristos 		exit(1);
792335f7552Schristos 	}
793335f7552Schristos #   endif
794abb0f93cSkardel 	return iface;
795abb0f93cSkardel }
796abb0f93cSkardel 
797abb0f93cSkardel 
798abb0f93cSkardel /*
799abb0f93cSkardel  * return interface storage into free memory pool
800abb0f93cSkardel  */
801335f7552Schristos static void
delete_interface(endpt * ep)802abb0f93cSkardel delete_interface(
80345530cf1Skardel 	endpt *ep
804abb0f93cSkardel 	)
805abb0f93cSkardel {
806335f7552Schristos #    ifdef HAVE_IO_COMPLETION_PORT
807335f7552Schristos 	io_completion_port_remove_interface(ep);
808335f7552Schristos #    endif
80945530cf1Skardel 	free(ep);
810abb0f93cSkardel }
811abb0f93cSkardel 
812abb0f93cSkardel 
813abb0f93cSkardel /*
814abb0f93cSkardel  * link interface into list of known interfaces
815abb0f93cSkardel  */
816abb0f93cSkardel static void
add_interface(endpt * ep)817abb0f93cSkardel add_interface(
81845530cf1Skardel 	endpt *	ep
819abb0f93cSkardel 	)
820abb0f93cSkardel {
82145530cf1Skardel 	endpt **	pmclisthead;
82245530cf1Skardel 	endpt *		scan;
82345530cf1Skardel 	endpt *		scan_next;
82445530cf1Skardel 	endpt *		unlinked;
82545530cf1Skardel 	sockaddr_u *	addr;
82645530cf1Skardel 	int		ep_local;
82745530cf1Skardel 	int		scan_local;
82845530cf1Skardel 	int		same_subnet;
82945530cf1Skardel 	int		ep_univ_iid;	/* iface ID from MAC address */
83045530cf1Skardel 	int		scan_univ_iid;	/* see RFC 4291 */
83145530cf1Skardel 	int		ep_privacy;	/* random local iface ID */
83245530cf1Skardel 	int		scan_privacy;	/* see RFC 4941 */
83345530cf1Skardel 	int		rc;
83445530cf1Skardel 
835b3d6264cSchristos 	/* Calculate the refid */
83645530cf1Skardel 	ep->addr_refid = addr2refid(&ep->sin);
837b3d6264cSchristos 	/* link at tail so ntpdc -c ifstats index increases each row */
838b3d6264cSchristos 	LINK_TAIL_SLIST(ep_list, ep, elink, endpt);
839abb0f93cSkardel 	ninterfaces++;
84045530cf1Skardel #ifdef MCAST
84145530cf1Skardel 	/* the rest is for enabled multicast-capable addresses only */
84245530cf1Skardel 	if (ep->ignore_packets || !(INT_MULTICAST & ep->flags) ||
84345530cf1Skardel 	    INT_LOOPBACK & ep->flags)
84445530cf1Skardel 		return;
84545530cf1Skardel # ifndef INCLUDE_IPV6_MULTICAST_SUPPORT
84645530cf1Skardel 	if (AF_INET6 == ep->family)
84745530cf1Skardel 		return;
84845530cf1Skardel # endif
84945530cf1Skardel 	pmclisthead = (AF_INET == ep->family)
85045530cf1Skardel 			 ? &mc4_list
85145530cf1Skardel 			 : &mc6_list;
85245530cf1Skardel 
85345530cf1Skardel 	if (AF_INET6 == ep->family) {
85445530cf1Skardel 		ep_local =
85545530cf1Skardel 		    IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(&ep->sin)) ||
85645530cf1Skardel 		    IN6_IS_ADDR_SITELOCAL(PSOCK_ADDR6(&ep->sin));
85745530cf1Skardel 		ep_univ_iid = IS_IID_UNIV(&ep->sin);
85845530cf1Skardel 		ep_privacy = !!(INT_PRIVACY & ep->flags);
85945530cf1Skardel 	} else {
86045530cf1Skardel 		ep_local = FALSE;
86145530cf1Skardel 		ep_univ_iid = FALSE;
86245530cf1Skardel 		ep_privacy = FALSE;
86345530cf1Skardel 	}
86445530cf1Skardel 	DPRINTF(4, ("add_interface mcast-capable %s%s%s%s\n",
86545530cf1Skardel 		    stoa(&ep->sin),
86645530cf1Skardel 		    (ep_local) ? " link/scope-local" : "",
86745530cf1Skardel 		    (ep_univ_iid) ? " univ-IID" : "",
86845530cf1Skardel 		    (ep_privacy) ? " privacy" : ""));
86945530cf1Skardel 	/*
87045530cf1Skardel 	 * If we have multiple local addresses on the same network
87145530cf1Skardel 	 * interface, and some are link- or site-local, do not multicast
87245530cf1Skardel 	 * out from the link-/site-local addresses by default, to avoid
87345530cf1Skardel 	 * duplicate manycastclient associations between v6 peers using
87445530cf1Skardel 	 * link-local and global addresses.  link-local can still be
87545530cf1Skardel 	 * chosen using "nic ignore myv6globalprefix::/64".
87645530cf1Skardel 	 * Similarly, if we have multiple global addresses from the same
87745530cf1Skardel 	 * prefix on the same network interface, multicast from one,
87845530cf1Skardel 	 * preferring EUI-64, then static, then least RFC 4941 privacy
87945530cf1Skardel 	 * addresses.
88045530cf1Skardel 	 */
88145530cf1Skardel 	for (scan = *pmclisthead; scan != NULL; scan = scan_next) {
88245530cf1Skardel 		scan_next = scan->mclink;
88345530cf1Skardel 		if (ep->family != scan->family)
88445530cf1Skardel 			continue;
88545530cf1Skardel 		if (strcmp(ep->name, scan->name))
88645530cf1Skardel 			continue;
88745530cf1Skardel 		same_subnet = addr_samesubnet(&ep->sin, &ep->mask,
88845530cf1Skardel 					      &scan->sin, &scan->mask);
88945530cf1Skardel 		if (AF_INET6 == ep->family) {
89045530cf1Skardel 			addr = &scan->sin;
89145530cf1Skardel 			scan_local =
89245530cf1Skardel 			    IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(addr)) ||
89345530cf1Skardel 			    IN6_IS_ADDR_SITELOCAL(PSOCK_ADDR6(addr));
89445530cf1Skardel 			scan_univ_iid = IS_IID_UNIV(addr);
89545530cf1Skardel 			scan_privacy = !!(INT_PRIVACY & scan->flags);
89645530cf1Skardel 		} else {
89745530cf1Skardel 			scan_local = FALSE;
89845530cf1Skardel 			scan_univ_iid = FALSE;
89945530cf1Skardel 			scan_privacy = FALSE;
90045530cf1Skardel 		}
90145530cf1Skardel 		DPRINTF(4, ("add_interface mcast-capable scan %s%s%s%s\n",
90245530cf1Skardel 			    stoa(&scan->sin),
90345530cf1Skardel 			    (scan_local) ? " link/scope-local" : "",
90445530cf1Skardel 			    (scan_univ_iid) ? " univ-IID" : "",
90545530cf1Skardel 			    (scan_privacy) ? " privacy" : ""));
90645530cf1Skardel 		if ((ep_local && !scan_local) || (same_subnet &&
90745530cf1Skardel 		    ((ep_privacy && !scan_privacy) ||
90845530cf1Skardel 		     (!ep_univ_iid && scan_univ_iid)))) {
90945530cf1Skardel 			DPRINTF(4, ("did not add %s to %s of IPv6 multicast-capable list which already has %s\n",
91045530cf1Skardel 				stoa(&ep->sin),
91145530cf1Skardel 				(ep_local)
91245530cf1Skardel 				    ? "tail"
91345530cf1Skardel 				    : "head",
91445530cf1Skardel 				stoa(&scan->sin)));
91545530cf1Skardel 			return;
91645530cf1Skardel 		}
91745530cf1Skardel 		if ((scan_local && !ep_local) || (same_subnet &&
91845530cf1Skardel 		    ((scan_privacy && !ep_privacy) ||
91945530cf1Skardel 		     (!scan_univ_iid && ep_univ_iid)))) {
92045530cf1Skardel 			UNLINK_SLIST(unlinked, *pmclisthead,
92145530cf1Skardel 				     scan, mclink, endpt);
92245530cf1Skardel 			DPRINTF(4, ("%s %s from IPv6 multicast-capable list to add %s\n",
92345530cf1Skardel 				(unlinked != scan)
92445530cf1Skardel 				    ? "Failed to remove"
92545530cf1Skardel 				    : "removed",
92645530cf1Skardel 				stoa(&scan->sin), stoa(&ep->sin)));
92745530cf1Skardel 		}
92845530cf1Skardel 	}
92945530cf1Skardel 	/*
93045530cf1Skardel 	 * Add link/site local at the tail of the multicast-
93145530cf1Skardel 	 * capable unicast interfaces list, so that ntpd will
93245530cf1Skardel 	 * send from global addresses before link-/site-local
93345530cf1Skardel 	 * ones.
93445530cf1Skardel 	 */
93545530cf1Skardel 	if (ep_local)
93645530cf1Skardel 		LINK_TAIL_SLIST(*pmclisthead, ep, mclink, endpt);
93745530cf1Skardel 	else
93845530cf1Skardel 		LINK_SLIST(*pmclisthead, ep, mclink);
93945530cf1Skardel 	DPRINTF(4, ("added %s to %s of IPv%s multicast-capable unicast local address list\n",
94045530cf1Skardel 		stoa(&ep->sin),
94145530cf1Skardel 		(ep_local)
94245530cf1Skardel 		    ? "tail"
94345530cf1Skardel 		    : "head",
94445530cf1Skardel 		(AF_INET == ep->family)
94545530cf1Skardel 		    ? "4"
94645530cf1Skardel 		    : "6"));
94745530cf1Skardel 
948b3d6264cSchristos 	if (INVALID_SOCKET == ep->fd)
949b3d6264cSchristos 		return;
950b3d6264cSchristos 
95145530cf1Skardel 	/*
95245530cf1Skardel 	 * select the local address from which to send to multicast.
95345530cf1Skardel 	 */
95445530cf1Skardel 	switch (AF(&ep->sin)) {
955b3d6264cSchristos 
95645530cf1Skardel 	case AF_INET :
95745530cf1Skardel 		rc = setsockopt(ep->fd, IPPROTO_IP,
95845530cf1Skardel 				IP_MULTICAST_IF,
95945530cf1Skardel 				(void *)&NSRCADR(&ep->sin),
96045530cf1Skardel 				sizeof(NSRCADR(&ep->sin)));
96145530cf1Skardel 		if (rc)
96245530cf1Skardel 			msyslog(LOG_ERR,
96345530cf1Skardel 				"setsockopt IP_MULTICAST_IF %s fails: %m",
96445530cf1Skardel 				stoa(&ep->sin));
96545530cf1Skardel 		break;
966b3d6264cSchristos 
96745530cf1Skardel # ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
96845530cf1Skardel 	case AF_INET6 :
96945530cf1Skardel 		rc = setsockopt(ep->fd, IPPROTO_IPV6,
97045530cf1Skardel 				 IPV6_MULTICAST_IF,
97145530cf1Skardel 				 (void *)&ep->ifindex,
97245530cf1Skardel 				 sizeof(ep->ifindex));
973b3d6264cSchristos 		/* do not complain if bound addr scope is ifindex */
974b3d6264cSchristos 		if (rc && ep->ifindex != SCOPE(&ep->sin))
97545530cf1Skardel 			msyslog(LOG_ERR,
97645530cf1Skardel 				"setsockopt IPV6_MULTICAST_IF %u for %s fails: %m",
97745530cf1Skardel 				ep->ifindex, stoa(&ep->sin));
97845530cf1Skardel 		break;
97945530cf1Skardel # endif
98045530cf1Skardel 	}
98145530cf1Skardel #endif	/* MCAST */
982abb0f93cSkardel }
983abb0f93cSkardel 
984abb0f93cSkardel 
985abb0f93cSkardel /*
986abb0f93cSkardel  * remove interface from known interface list and clean up
987abb0f93cSkardel  * associated resources
988abb0f93cSkardel  */
989abb0f93cSkardel static void
remove_interface(endpt * ep)990abb0f93cSkardel remove_interface(
99145530cf1Skardel 	endpt *	ep
992abb0f93cSkardel 	)
993abb0f93cSkardel {
99445530cf1Skardel 	endpt *		unlinked;
99545530cf1Skardel 	endpt **	pmclisthead;
996abb0f93cSkardel 	sockaddr_u	resmask;
997abb0f93cSkardel 
99845530cf1Skardel 	UNLINK_SLIST(unlinked, ep_list, ep, elink, endpt);
99945530cf1Skardel 	if (!ep->ignore_packets && INT_MULTICAST & ep->flags) {
100045530cf1Skardel 		pmclisthead = (AF_INET == ep->family)
100145530cf1Skardel 				 ? &mc4_list
100245530cf1Skardel 				 : &mc6_list;
100345530cf1Skardel 		UNLINK_SLIST(unlinked, *pmclisthead, ep, mclink, endpt);
100445530cf1Skardel 		DPRINTF(4, ("%s %s IPv%s multicast-capable unicast local address list\n",
100545530cf1Skardel 			stoa(&ep->sin),
100645530cf1Skardel 			(unlinked != NULL)
100745530cf1Skardel 			    ? "removed from"
100845530cf1Skardel 			    : "not found on",
100945530cf1Skardel 			(AF_INET == ep->family)
101045530cf1Skardel 			    ? "4"
101145530cf1Skardel 			    : "6"));
101245530cf1Skardel 	}
101345530cf1Skardel 	delete_interface_from_list(ep);
1014abb0f93cSkardel 
101545530cf1Skardel 	if (ep->fd != INVALID_SOCKET) {
1016abb0f93cSkardel 		msyslog(LOG_INFO,
1017abb0f93cSkardel 			"Deleting interface #%d %s, %s#%d, interface stats: received=%ld, sent=%ld, dropped=%ld, active_time=%ld secs",
101845530cf1Skardel 			ep->ifnum,
101945530cf1Skardel 			ep->name,
102045530cf1Skardel 			stoa(&ep->sin),
102145530cf1Skardel 			SRCPORT(&ep->sin),
102245530cf1Skardel 			ep->received,
102345530cf1Skardel 			ep->sent,
102445530cf1Skardel 			ep->notsent,
102545530cf1Skardel 			current_time - ep->starttime);
1026335f7552Schristos #	    ifdef HAVE_IO_COMPLETION_PORT
1027335f7552Schristos 		io_completion_port_remove_socket(ep->fd, ep);
1028335f7552Schristos #	    endif
102945530cf1Skardel 		close_and_delete_fd_from_list(ep->fd);
1030b3d6264cSchristos 		ep->fd = INVALID_SOCKET;
1031abb0f93cSkardel 	}
1032abb0f93cSkardel 
103345530cf1Skardel 	if (ep->bfd != INVALID_SOCKET) {
1034abb0f93cSkardel 		msyslog(LOG_INFO,
1035b3d6264cSchristos 			"stop listening for broadcasts to %s on interface #%d %s",
1036b3d6264cSchristos 			stoa(&ep->bcast), ep->ifnum, ep->name);
1037335f7552Schristos #	    ifdef HAVE_IO_COMPLETION_PORT
1038335f7552Schristos 		io_completion_port_remove_socket(ep->bfd, ep);
1039335f7552Schristos #	    endif
104045530cf1Skardel 		close_and_delete_fd_from_list(ep->bfd);
1041b3d6264cSchristos 		ep->bfd = INVALID_SOCKET;
1042abb0f93cSkardel 	}
1043335f7552Schristos #   ifdef HAVE_IO_COMPLETION_PORT
1044335f7552Schristos 	io_completion_port_remove_interface(ep);
1045335f7552Schristos #   endif
1046abb0f93cSkardel 
1047abb0f93cSkardel 	ninterfaces--;
1048b3d6264cSchristos 	mon_clearinterface(ep);
1049abb0f93cSkardel 
1050abb0f93cSkardel 	/* remove restrict interface entry */
105145530cf1Skardel 	SET_HOSTMASK(&resmask, AF(&ep->sin));
105245530cf1Skardel 	hack_restrict(RESTRICT_REMOVEIF, &ep->sin, &resmask,
1053169394abSchristos 		      -3, RESM_NTPONLY | RESM_INTERFACE, RES_IGNORE, 0);
1054abb0f93cSkardel }
1055abb0f93cSkardel 
1056abb0f93cSkardel 
1057abb0f93cSkardel static void
log_listen_address(endpt * ep)105845530cf1Skardel log_listen_address(
105945530cf1Skardel 	endpt *	ep
1060abb0f93cSkardel 	)
1061abb0f93cSkardel {
1062b3d6264cSchristos 	msyslog(LOG_INFO, "%s on %d %s %s",
106345530cf1Skardel 		(ep->ignore_packets)
1064abb0f93cSkardel 		    ? "Listen and drop"
1065abb0f93cSkardel 		    : "Listen normally",
106645530cf1Skardel 		ep->ifnum,
106745530cf1Skardel 		ep->name,
1068b3d6264cSchristos 		sptoa(&ep->sin));
1069abb0f93cSkardel }
1070abb0f93cSkardel 
1071abb0f93cSkardel 
1072abb0f93cSkardel static void
create_wildcards(u_short port)1073abb0f93cSkardel create_wildcards(
1074abb0f93cSkardel 	u_short	port
1075abb0f93cSkardel 	)
1076abb0f93cSkardel {
107743476b9eSkardel 	int			v4wild;
107843476b9eSkardel #ifdef INCLUDE_IPV6_SUPPORT
107943476b9eSkardel 	int			v6wild;
108043476b9eSkardel #endif
1081abb0f93cSkardel 	sockaddr_u		wildaddr;
1082abb0f93cSkardel 	nic_rule_action		action;
1083abb0f93cSkardel 	struct interface *	wildif;
1084abb0f93cSkardel 
1085abb0f93cSkardel 	/*
1086abb0f93cSkardel 	 * silence "potentially uninitialized" warnings from VC9
1087abb0f93cSkardel 	 * failing to follow the logic.  Ideally action could remain
1088abb0f93cSkardel 	 * uninitialized, and the memset be the first statement under
1089abb0f93cSkardel 	 * the first if (v4wild).
1090abb0f93cSkardel 	 */
1091abb0f93cSkardel 	action = ACTION_LISTEN;
1092b3d6264cSchristos 	ZERO(wildaddr);
1093abb0f93cSkardel 
1094abb0f93cSkardel #ifdef INCLUDE_IPV6_SUPPORT
1095abb0f93cSkardel 	/*
1096abb0f93cSkardel 	 * create pseudo-interface with wildcard IPv6 address
1097abb0f93cSkardel 	 */
1098abb0f93cSkardel 	v6wild = ipv6_works;
1099abb0f93cSkardel 	if (v6wild) {
1100abb0f93cSkardel 		/* set wildaddr to the v6 wildcard address :: */
1101b3d6264cSchristos 		ZERO(wildaddr);
1102abb0f93cSkardel 		AF(&wildaddr) = AF_INET6;
1103abb0f93cSkardel 		SET_ADDR6N(&wildaddr, in6addr_any);
1104abb0f93cSkardel 		SET_PORT(&wildaddr, port);
1105abb0f93cSkardel 		SET_SCOPE(&wildaddr, 0);
1106abb0f93cSkardel 
1107abb0f93cSkardel 		/* check for interface/nic rules affecting the wildcard */
110845530cf1Skardel 		action = interface_action(NULL, &wildaddr, 0);
1109abb0f93cSkardel 		v6wild = (ACTION_IGNORE != action);
1110abb0f93cSkardel 	}
1111abb0f93cSkardel 	if (v6wild) {
1112abb0f93cSkardel 		wildif = new_interface(NULL);
1113abb0f93cSkardel 
1114b3d6264cSchristos 		strlcpy(wildif->name, "v6wildcard", sizeof(wildif->name));
1115abb0f93cSkardel 		memcpy(&wildif->sin, &wildaddr, sizeof(wildif->sin));
1116abb0f93cSkardel 		wildif->family = AF_INET6;
1117abb0f93cSkardel 		AF(&wildif->mask) = AF_INET6;
1118abb0f93cSkardel 		SET_ONESMASK(&wildif->mask);
1119abb0f93cSkardel 
1120abb0f93cSkardel 		wildif->flags = INT_UP | INT_WILDCARD;
1121abb0f93cSkardel 		wildif->ignore_packets = (ACTION_DROP == action);
1122abb0f93cSkardel 
1123abb0f93cSkardel 		wildif->fd = open_socket(&wildif->sin, 0, 1, wildif);
1124abb0f93cSkardel 
1125abb0f93cSkardel 		if (wildif->fd != INVALID_SOCKET) {
1126abb0f93cSkardel 			wildipv6 = wildif;
1127abb0f93cSkardel 			any6_interface = wildif;
1128abb0f93cSkardel 			add_addr_to_list(&wildif->sin, wildif);
1129abb0f93cSkardel 			add_interface(wildif);
113045530cf1Skardel 			log_listen_address(wildif);
1131abb0f93cSkardel 		} else {
1132abb0f93cSkardel 			msyslog(LOG_ERR,
1133abb0f93cSkardel 				"unable to bind to wildcard address %s - another process may be running - EXITING",
1134abb0f93cSkardel 				stoa(&wildif->sin));
1135abb0f93cSkardel 			exit(1);
1136abb0f93cSkardel 		}
1137abb0f93cSkardel 		DPRINT_INTERFACE(2, (wildif, "created ", "\n"));
1138abb0f93cSkardel 	}
1139abb0f93cSkardel #endif
1140b3d6264cSchristos 
1141b3d6264cSchristos 	/*
1142b3d6264cSchristos 	 * create pseudo-interface with wildcard IPv4 address
1143b3d6264cSchristos 	 */
1144b3d6264cSchristos 	v4wild = ipv4_works;
1145b3d6264cSchristos 	if (v4wild) {
1146b3d6264cSchristos 		/* set wildaddr to the v4 wildcard address 0.0.0.0 */
1147b3d6264cSchristos 		AF(&wildaddr) = AF_INET;
1148b3d6264cSchristos 		SET_ADDR4N(&wildaddr, INADDR_ANY);
1149b3d6264cSchristos 		SET_PORT(&wildaddr, port);
1150b3d6264cSchristos 
1151b3d6264cSchristos 		/* check for interface/nic rules affecting the wildcard */
1152b3d6264cSchristos 		action = interface_action(NULL, &wildaddr, 0);
1153b3d6264cSchristos 		v4wild = (ACTION_IGNORE != action);
1154b3d6264cSchristos 	}
1155b3d6264cSchristos 	if (v4wild) {
1156b3d6264cSchristos 		wildif = new_interface(NULL);
1157b3d6264cSchristos 
1158b3d6264cSchristos 		strlcpy(wildif->name, "v4wildcard", sizeof(wildif->name));
1159b3d6264cSchristos 		memcpy(&wildif->sin, &wildaddr, sizeof(wildif->sin));
1160b3d6264cSchristos 		wildif->family = AF_INET;
1161b3d6264cSchristos 		AF(&wildif->mask) = AF_INET;
1162b3d6264cSchristos 		SET_ONESMASK(&wildif->mask);
1163b3d6264cSchristos 
1164b3d6264cSchristos 		wildif->flags = INT_BROADCAST | INT_UP | INT_WILDCARD;
1165b3d6264cSchristos 		wildif->ignore_packets = (ACTION_DROP == action);
1166b3d6264cSchristos #if defined(MCAST)
1167b3d6264cSchristos 		/*
1168b3d6264cSchristos 		 * enable multicast reception on the broadcast socket
1169b3d6264cSchristos 		 */
1170b3d6264cSchristos 		AF(&wildif->bcast) = AF_INET;
1171b3d6264cSchristos 		SET_ADDR4N(&wildif->bcast, INADDR_ANY);
1172b3d6264cSchristos 		SET_PORT(&wildif->bcast, port);
1173b3d6264cSchristos #endif /* MCAST */
1174b3d6264cSchristos 		wildif->fd = open_socket(&wildif->sin, 0, 1, wildif);
1175b3d6264cSchristos 
1176b3d6264cSchristos 		if (wildif->fd != INVALID_SOCKET) {
1177b3d6264cSchristos 			wildipv4 = wildif;
1178b3d6264cSchristos 			any_interface = wildif;
1179b3d6264cSchristos 
1180b3d6264cSchristos 			add_addr_to_list(&wildif->sin, wildif);
1181b3d6264cSchristos 			add_interface(wildif);
1182b3d6264cSchristos 			log_listen_address(wildif);
1183b3d6264cSchristos 		} else {
1184b3d6264cSchristos 			msyslog(LOG_ERR,
1185b3d6264cSchristos 				"unable to bind to wildcard address %s - another process may be running - EXITING",
1186b3d6264cSchristos 				stoa(&wildif->sin));
1187b3d6264cSchristos 			exit(1);
1188b3d6264cSchristos 		}
1189b3d6264cSchristos 		DPRINT_INTERFACE(2, (wildif, "created ", "\n"));
1190b3d6264cSchristos 	}
1191abb0f93cSkardel }
1192abb0f93cSkardel 
1193abb0f93cSkardel 
1194abb0f93cSkardel /*
1195abb0f93cSkardel  * add_nic_rule() -- insert a rule entry at the head of nic_rule_list.
1196abb0f93cSkardel  */
1197abb0f93cSkardel void
add_nic_rule(nic_rule_match match_type,const char * if_name,int prefixlen,nic_rule_action action)1198abb0f93cSkardel add_nic_rule(
1199abb0f93cSkardel 	nic_rule_match	match_type,
1200abb0f93cSkardel 	const char *	if_name,	/* interface name or numeric address */
1201abb0f93cSkardel 	int		prefixlen,
1202abb0f93cSkardel 	nic_rule_action	action
1203abb0f93cSkardel 	)
1204abb0f93cSkardel {
1205abb0f93cSkardel 	nic_rule *	rule;
1206abb0f93cSkardel 	isc_boolean_t	is_ip;
1207abb0f93cSkardel 
1208b3d6264cSchristos 	rule = emalloc_zero(sizeof(*rule));
1209abb0f93cSkardel 	rule->match_type = match_type;
1210abb0f93cSkardel 	rule->prefixlen = prefixlen;
1211abb0f93cSkardel 	rule->action = action;
1212abb0f93cSkardel 
1213abb0f93cSkardel 	if (MATCH_IFNAME == match_type) {
121409f14f80Schristos 		REQUIRE(NULL != if_name);
1215abb0f93cSkardel 		rule->if_name = estrdup(if_name);
1216abb0f93cSkardel 	} else if (MATCH_IFADDR == match_type) {
121709f14f80Schristos 		REQUIRE(NULL != if_name);
121845530cf1Skardel 		/* set rule->addr */
1219b3d6264cSchristos 		is_ip = is_ip_address(if_name, AF_UNSPEC, &rule->addr);
122009f14f80Schristos 		REQUIRE(is_ip);
1221abb0f93cSkardel 	} else
122209f14f80Schristos 		REQUIRE(NULL == if_name);
1223abb0f93cSkardel 
1224abb0f93cSkardel 	LINK_SLIST(nic_rule_list, rule, next);
1225abb0f93cSkardel }
1226abb0f93cSkardel 
1227abb0f93cSkardel 
1228abb0f93cSkardel #ifdef DEBUG
1229abb0f93cSkardel static const char *
action_text(nic_rule_action action)1230abb0f93cSkardel action_text(
1231abb0f93cSkardel 	nic_rule_action	action
1232abb0f93cSkardel 	)
1233abb0f93cSkardel {
1234abb0f93cSkardel 	const char *t;
1235abb0f93cSkardel 
1236abb0f93cSkardel 	switch (action) {
1237abb0f93cSkardel 
1238abb0f93cSkardel 	default:
1239abb0f93cSkardel 		t = "ERROR";	/* quiet uninit warning */
1240abb0f93cSkardel 		DPRINTF(1, ("fatal: unknown nic_rule_action %d\n",
1241abb0f93cSkardel 			    action));
124209f14f80Schristos 		ENSURE(0);
1243abb0f93cSkardel 		break;
1244abb0f93cSkardel 
1245abb0f93cSkardel 	case ACTION_LISTEN:
1246abb0f93cSkardel 		t = "listen";
1247abb0f93cSkardel 		break;
1248abb0f93cSkardel 
1249abb0f93cSkardel 	case ACTION_IGNORE:
1250abb0f93cSkardel 		t = "ignore";
1251abb0f93cSkardel 		break;
1252abb0f93cSkardel 
1253abb0f93cSkardel 	case ACTION_DROP:
1254abb0f93cSkardel 		t = "drop";
1255abb0f93cSkardel 		break;
1256abb0f93cSkardel 	}
1257abb0f93cSkardel 
1258abb0f93cSkardel 	return t;
1259abb0f93cSkardel }
1260abb0f93cSkardel #endif	/* DEBUG */
1261abb0f93cSkardel 
1262abb0f93cSkardel 
1263abb0f93cSkardel static nic_rule_action
interface_action(char * if_name,sockaddr_u * if_addr,u_int32 if_flags)1264abb0f93cSkardel interface_action(
1265abb0f93cSkardel 	char *		if_name,
126645530cf1Skardel 	sockaddr_u *	if_addr,
126745530cf1Skardel 	u_int32		if_flags
1268abb0f93cSkardel 	)
1269abb0f93cSkardel {
1270abb0f93cSkardel 	nic_rule *	rule;
1271abb0f93cSkardel 	int		isloopback;
1272abb0f93cSkardel 	int		iswildcard;
1273abb0f93cSkardel 
1274b3d6264cSchristos 	DPRINTF(4, ("interface_action: interface %s ",
1275b3d6264cSchristos 		    (if_name != NULL) ? if_name : "wildcard"));
1276abb0f93cSkardel 
127745530cf1Skardel 	iswildcard = is_wildcard_addr(if_addr);
1278b3d6264cSchristos 	isloopback = !!(INT_LOOPBACK & if_flags);
1279abb0f93cSkardel 
1280abb0f93cSkardel 	/*
1281abb0f93cSkardel 	 * Find any matching NIC rule from --interface / -I or ntp.conf
1282abb0f93cSkardel 	 * interface/nic rules.
1283abb0f93cSkardel 	 */
1284abb0f93cSkardel 	for (rule = nic_rule_list; rule != NULL; rule = rule->next) {
1285abb0f93cSkardel 
1286abb0f93cSkardel 		switch (rule->match_type) {
1287abb0f93cSkardel 
1288abb0f93cSkardel 		case MATCH_ALL:
1289abb0f93cSkardel 			/* loopback and wildcard excluded from "all" */
1290abb0f93cSkardel 			if (isloopback || iswildcard)
1291abb0f93cSkardel 				break;
1292abb0f93cSkardel 			DPRINTF(4, ("nic all %s\n",
1293abb0f93cSkardel 			    action_text(rule->action)));
1294abb0f93cSkardel 			return rule->action;
1295abb0f93cSkardel 
1296abb0f93cSkardel 		case MATCH_IPV4:
129745530cf1Skardel 			if (IS_IPV4(if_addr)) {
1298abb0f93cSkardel 				DPRINTF(4, ("nic ipv4 %s\n",
1299abb0f93cSkardel 				    action_text(rule->action)));
1300abb0f93cSkardel 				return rule->action;
1301abb0f93cSkardel 			}
1302abb0f93cSkardel 			break;
1303abb0f93cSkardel 
1304abb0f93cSkardel 		case MATCH_IPV6:
130545530cf1Skardel 			if (IS_IPV6(if_addr)) {
1306abb0f93cSkardel 				DPRINTF(4, ("nic ipv6 %s\n",
1307abb0f93cSkardel 				    action_text(rule->action)));
1308abb0f93cSkardel 				return rule->action;
1309abb0f93cSkardel 			}
1310abb0f93cSkardel 			break;
1311abb0f93cSkardel 
1312abb0f93cSkardel 		case MATCH_WILDCARD:
1313abb0f93cSkardel 			if (iswildcard) {
1314abb0f93cSkardel 				DPRINTF(4, ("nic wildcard %s\n",
1315abb0f93cSkardel 				    action_text(rule->action)));
1316abb0f93cSkardel 				return rule->action;
1317abb0f93cSkardel 			}
1318abb0f93cSkardel 			break;
1319abb0f93cSkardel 
1320abb0f93cSkardel 		case MATCH_IFADDR:
1321abb0f93cSkardel 			if (rule->prefixlen != -1) {
132245530cf1Skardel 				if (addr_eqprefix(if_addr, &rule->addr,
132345530cf1Skardel 						  rule->prefixlen)) {
1324abb0f93cSkardel 
1325abb0f93cSkardel 					DPRINTF(4, ("subnet address match - %s\n",
1326abb0f93cSkardel 					    action_text(rule->action)));
1327abb0f93cSkardel 					return rule->action;
1328abb0f93cSkardel 				}
1329abb0f93cSkardel 			} else
133045530cf1Skardel 				if (SOCK_EQ(if_addr, &rule->addr)) {
1331abb0f93cSkardel 
1332abb0f93cSkardel 					DPRINTF(4, ("address match - %s\n",
1333abb0f93cSkardel 					    action_text(rule->action)));
1334abb0f93cSkardel 					return rule->action;
1335abb0f93cSkardel 				}
1336abb0f93cSkardel 			break;
1337abb0f93cSkardel 
1338abb0f93cSkardel 		case MATCH_IFNAME:
1339abb0f93cSkardel 			if (if_name != NULL
1340ad131110Schristos #if defined(HAVE_FNMATCH) && defined(FNM_CASEFOLD)
1341ad131110Schristos 			    && !fnmatch(rule->if_name, if_name, FNM_CASEFOLD)
1342ad131110Schristos #else
1343ad131110Schristos 			    && !strcasecmp(if_name, rule->if_name)
1344ad131110Schristos #endif
1345ad131110Schristos 			    ) {
1346abb0f93cSkardel 
1347abb0f93cSkardel 				DPRINTF(4, ("interface name match - %s\n",
1348abb0f93cSkardel 				    action_text(rule->action)));
1349abb0f93cSkardel 				return rule->action;
1350abb0f93cSkardel 			}
1351abb0f93cSkardel 			break;
1352abb0f93cSkardel 		}
1353abb0f93cSkardel 	}
1354abb0f93cSkardel 
1355abb0f93cSkardel 	/*
1356abb0f93cSkardel 	 * Unless explicitly disabled such as with "nic ignore ::1"
1357abb0f93cSkardel 	 * listen on loopback addresses.  Since ntpq and ntpdc query
1358abb0f93cSkardel 	 * "localhost" by default, which typically resolves to ::1 and
1359abb0f93cSkardel 	 * 127.0.0.1, it's useful to default to listening on both.
1360abb0f93cSkardel 	 */
1361abb0f93cSkardel 	if (isloopback) {
1362abb0f93cSkardel 		DPRINTF(4, ("default loopback listen\n"));
1363abb0f93cSkardel 		return ACTION_LISTEN;
1364abb0f93cSkardel 	}
1365abb0f93cSkardel 
1366abb0f93cSkardel 	/*
1367abb0f93cSkardel 	 * Treat wildcard addresses specially.  If there is no explicit
1368abb0f93cSkardel 	 * "nic ... wildcard" or "nic ... 0.0.0.0" or "nic ... ::" rule
1369abb0f93cSkardel 	 * default to drop.
1370abb0f93cSkardel 	 */
1371abb0f93cSkardel 	if (iswildcard) {
1372abb0f93cSkardel 		DPRINTF(4, ("default wildcard drop\n"));
1373abb0f93cSkardel 		return ACTION_DROP;
1374abb0f93cSkardel 	}
1375abb0f93cSkardel 
1376abb0f93cSkardel 	/*
1377abb0f93cSkardel 	 * Check for "virtual IP" (colon in the interface name) after
1378abb0f93cSkardel 	 * the rules so that "ntpd --interface eth0:1 -novirtualips"
1379abb0f93cSkardel 	 * does indeed listen on eth0:1's addresses.
1380abb0f93cSkardel 	 */
1381abb0f93cSkardel 	if (!listen_to_virtual_ips && if_name != NULL
1382abb0f93cSkardel 	    && (strchr(if_name, ':') != NULL)) {
1383abb0f93cSkardel 
1384abb0f93cSkardel 		DPRINTF(4, ("virtual ip - ignore\n"));
1385abb0f93cSkardel 		return ACTION_IGNORE;
1386abb0f93cSkardel 	}
1387abb0f93cSkardel 
1388abb0f93cSkardel 	/*
1389abb0f93cSkardel 	 * If there are no --interface/-I command-line options and no
1390abb0f93cSkardel 	 * interface/nic rules in ntp.conf, the default action is to
1391abb0f93cSkardel 	 * listen.  In the presence of rules from either, the default
1392abb0f93cSkardel 	 * is to ignore.  This implements ntpd's traditional listen-
1393abb0f93cSkardel 	 * every default with no interface listen configuration, and
1394abb0f93cSkardel 	 * ensures a single -I eth0 or "nic listen eth0" means do not
1395abb0f93cSkardel 	 * listen on any other addresses.
1396abb0f93cSkardel 	 */
1397abb0f93cSkardel 	if (NULL == nic_rule_list) {
1398abb0f93cSkardel 		DPRINTF(4, ("default listen\n"));
1399abb0f93cSkardel 		return ACTION_LISTEN;
1400abb0f93cSkardel 	}
1401abb0f93cSkardel 
1402abb0f93cSkardel 	DPRINTF(4, ("implicit ignore\n"));
1403abb0f93cSkardel 	return ACTION_IGNORE;
1404abb0f93cSkardel }
1405abb0f93cSkardel 
1406abb0f93cSkardel 
1407abb0f93cSkardel static void
convert_isc_if(isc_interface_t * isc_if,endpt * itf,u_short port)1408abb0f93cSkardel convert_isc_if(
1409abb0f93cSkardel 	isc_interface_t *isc_if,
141045530cf1Skardel 	endpt *itf,
1411abb0f93cSkardel 	u_short port
1412abb0f93cSkardel 	)
1413abb0f93cSkardel {
141445530cf1Skardel 	const u_char v6loop[16] = {0, 0, 0, 0, 0, 0, 0, 0,
141545530cf1Skardel 				   0, 0, 0, 0, 0, 0, 0, 1};
141645530cf1Skardel 
1417b3d6264cSchristos 	strlcpy(itf->name, isc_if->name, sizeof(itf->name));
141845530cf1Skardel 	itf->ifindex = isc_if->ifindex;
1419abb0f93cSkardel 	itf->family = (u_short)isc_if->af;
1420abb0f93cSkardel 	AF(&itf->sin) = itf->family;
1421abb0f93cSkardel 	AF(&itf->mask) = itf->family;
1422abb0f93cSkardel 	AF(&itf->bcast) = itf->family;
1423abb0f93cSkardel 	SET_PORT(&itf->sin, port);
1424abb0f93cSkardel 	SET_PORT(&itf->mask, port);
1425abb0f93cSkardel 	SET_PORT(&itf->bcast, port);
1426abb0f93cSkardel 
1427abb0f93cSkardel 	if (IS_IPV4(&itf->sin)) {
1428abb0f93cSkardel 		NSRCADR(&itf->sin) = isc_if->address.type.in.s_addr;
1429abb0f93cSkardel 		NSRCADR(&itf->mask) = isc_if->netmask.type.in.s_addr;
1430abb0f93cSkardel 
1431abb0f93cSkardel 		if (isc_if->flags & INTERFACE_F_BROADCAST) {
1432abb0f93cSkardel 			itf->flags |= INT_BROADCAST;
1433abb0f93cSkardel 			NSRCADR(&itf->bcast) =
1434abb0f93cSkardel 			    isc_if->broadcast.type.in.s_addr;
1435abb0f93cSkardel 		}
1436abb0f93cSkardel 	}
1437abb0f93cSkardel #ifdef INCLUDE_IPV6_SUPPORT
1438abb0f93cSkardel 	else if (IS_IPV6(&itf->sin)) {
1439abb0f93cSkardel 		SET_ADDR6N(&itf->sin, isc_if->address.type.in6);
1440abb0f93cSkardel 		SET_ADDR6N(&itf->mask, isc_if->netmask.type.in6);
1441abb0f93cSkardel 
144245530cf1Skardel 		SET_SCOPE(&itf->sin, isc_if->address.zone);
1443abb0f93cSkardel 	}
1444abb0f93cSkardel #endif /* INCLUDE_IPV6_SUPPORT */
1445abb0f93cSkardel 
1446abb0f93cSkardel 
1447abb0f93cSkardel 	/* Process the rest of the flags */
1448abb0f93cSkardel 
1449abb0f93cSkardel 	itf->flags |=
1450abb0f93cSkardel 		  ((INTERFACE_F_UP & isc_if->flags)
1451abb0f93cSkardel 			? INT_UP : 0)
1452abb0f93cSkardel 		| ((INTERFACE_F_LOOPBACK & isc_if->flags)
1453abb0f93cSkardel 			? INT_LOOPBACK : 0)
1454abb0f93cSkardel 		| ((INTERFACE_F_POINTTOPOINT & isc_if->flags)
1455abb0f93cSkardel 			? INT_PPP : 0)
1456abb0f93cSkardel 		| ((INTERFACE_F_MULTICAST & isc_if->flags)
1457abb0f93cSkardel 			? INT_MULTICAST : 0)
145845530cf1Skardel 		| ((INTERFACE_F_PRIVACY & isc_if->flags)
145945530cf1Skardel 			? INT_PRIVACY : 0)
1460abb0f93cSkardel 		;
146145530cf1Skardel 
146245530cf1Skardel 	/*
146345530cf1Skardel 	 * Clear the loopback flag if the address is not localhost.
146445530cf1Skardel 	 * http://bugs.ntp.org/1683
146545530cf1Skardel 	 */
146645530cf1Skardel 	if (INT_LOOPBACK & itf->flags) {
146745530cf1Skardel 		if (AF_INET == itf->family) {
146845530cf1Skardel 			if (127 != (SRCADR(&itf->sin) >> 24))
146945530cf1Skardel 				itf->flags &= ~INT_LOOPBACK;
147045530cf1Skardel 		} else {
147145530cf1Skardel 			if (memcmp(v6loop, NSRCADR6(&itf->sin),
147245530cf1Skardel 				   sizeof(NSRCADR6(&itf->sin))))
147345530cf1Skardel 				itf->flags &= ~INT_LOOPBACK;
147445530cf1Skardel 		}
147545530cf1Skardel 	}
1476abb0f93cSkardel }
1477abb0f93cSkardel 
1478abb0f93cSkardel 
1479abb0f93cSkardel /*
1480abb0f93cSkardel  * refresh_interface
1481abb0f93cSkardel  *
1482abb0f93cSkardel  * some OSes have been observed to keep
1483abb0f93cSkardel  * cached routes even when more specific routes
1484abb0f93cSkardel  * become available.
1485abb0f93cSkardel  * this can be mitigated by re-binding
1486abb0f93cSkardel  * the socket.
1487abb0f93cSkardel  */
1488abb0f93cSkardel static int
refresh_interface(struct interface * interface)1489abb0f93cSkardel refresh_interface(
1490abb0f93cSkardel 	struct interface * interface
1491abb0f93cSkardel 	)
1492abb0f93cSkardel {
1493abb0f93cSkardel #ifdef  OS_MISSES_SPECIFIC_ROUTE_UPDATES
1494abb0f93cSkardel 	if (interface->fd != INVALID_SOCKET) {
1495b3d6264cSchristos 		int bcast = (interface->flags & INT_BCASTXMIT) != 0;
1496b3d6264cSchristos 		/* as we forcibly close() the socket remove the
1497b3d6264cSchristos 		   broadcast permission indication */
1498b3d6264cSchristos 		if (bcast)
1499b3d6264cSchristos 			socket_broadcast_disable(interface, &interface->sin);
1500b3d6264cSchristos 
1501abb0f93cSkardel 		close_and_delete_fd_from_list(interface->fd);
1502b3d6264cSchristos 
1503b3d6264cSchristos 		/* create new socket picking up a new first hop binding
1504b3d6264cSchristos 		   at connect() time */
1505abb0f93cSkardel 		interface->fd = open_socket(&interface->sin,
1506766d83b9Skardel 					    bcast, 0, interface);
1507abb0f93cSkardel 		 /*
1508abb0f93cSkardel 		  * reset TTL indication so TTL is is set again
1509abb0f93cSkardel 		  * next time around
1510abb0f93cSkardel 		  */
1511abb0f93cSkardel 		interface->last_ttl = 0;
1512abb0f93cSkardel 		return (interface->fd != INVALID_SOCKET);
1513abb0f93cSkardel 	} else
1514abb0f93cSkardel 		return 0;	/* invalid sockets are not refreshable */
1515abb0f93cSkardel #else /* !OS_MISSES_SPECIFIC_ROUTE_UPDATES */
1516abb0f93cSkardel 	return (interface->fd != INVALID_SOCKET);
1517abb0f93cSkardel #endif /* !OS_MISSES_SPECIFIC_ROUTE_UPDATES */
1518abb0f93cSkardel }
1519abb0f93cSkardel 
1520abb0f93cSkardel /*
1521abb0f93cSkardel  * interface_update - externally callable update function
1522abb0f93cSkardel  */
1523abb0f93cSkardel void
interface_update(interface_receiver_t receiver,void * data)1524abb0f93cSkardel interface_update(
1525abb0f93cSkardel 	interface_receiver_t	receiver,
1526abb0f93cSkardel 	void *			data)
1527abb0f93cSkardel {
1528abb0f93cSkardel 	int new_interface_found;
1529abb0f93cSkardel 
1530abb0f93cSkardel 	if (disable_dynamic_updates)
1531abb0f93cSkardel 		return;
1532abb0f93cSkardel 
1533abb0f93cSkardel 	BLOCKIO();
1534abb0f93cSkardel 	new_interface_found = update_interfaces(NTP_PORT, receiver, data);
1535abb0f93cSkardel 	UNBLOCKIO();
1536abb0f93cSkardel 
1537abb0f93cSkardel 	if (!new_interface_found)
1538abb0f93cSkardel 		return;
1539abb0f93cSkardel 
1540abb0f93cSkardel #ifdef DEBUG
1541abb0f93cSkardel 	msyslog(LOG_DEBUG, "new interface(s) found: waking up resolver");
1542abb0f93cSkardel #endif
1543b3d6264cSchristos 	interrupt_worker_sleep();
1544abb0f93cSkardel }
1545abb0f93cSkardel 
1546abb0f93cSkardel 
1547abb0f93cSkardel /*
1548abb0f93cSkardel  * sau_from_netaddr() - convert network address on-wire formats.
1549abb0f93cSkardel  * Convert from libisc's isc_netaddr_t to NTP's sockaddr_u
1550abb0f93cSkardel  */
1551abb0f93cSkardel void
sau_from_netaddr(sockaddr_u * psau,const isc_netaddr_t * pna)1552abb0f93cSkardel sau_from_netaddr(
1553abb0f93cSkardel 	sockaddr_u *psau,
1554abb0f93cSkardel 	const isc_netaddr_t *pna
1555abb0f93cSkardel 	)
1556abb0f93cSkardel {
1557b3d6264cSchristos 	ZERO_SOCK(psau);
1558abb0f93cSkardel 	AF(psau) = (u_short)pna->family;
1559abb0f93cSkardel 	switch (pna->family) {
1560abb0f93cSkardel 
1561abb0f93cSkardel 	case AF_INET:
1562abb0f93cSkardel 		memcpy(&psau->sa4.sin_addr, &pna->type.in,
1563abb0f93cSkardel 		       sizeof(psau->sa4.sin_addr));
1564abb0f93cSkardel 		break;
1565abb0f93cSkardel 
1566abb0f93cSkardel 	case AF_INET6:
1567abb0f93cSkardel 		memcpy(&psau->sa6.sin6_addr, &pna->type.in6,
1568abb0f93cSkardel 		       sizeof(psau->sa6.sin6_addr));
1569abb0f93cSkardel 		break;
1570abb0f93cSkardel 	}
1571abb0f93cSkardel }
1572abb0f93cSkardel 
1573abb0f93cSkardel 
1574abb0f93cSkardel static int
is_wildcard_addr(const sockaddr_u * psau)1575abb0f93cSkardel is_wildcard_addr(
157645530cf1Skardel 	const sockaddr_u *psau
1577abb0f93cSkardel 	)
1578abb0f93cSkardel {
1579abb0f93cSkardel 	if (IS_IPV4(psau) && !NSRCADR(psau))
1580abb0f93cSkardel 		return 1;
1581abb0f93cSkardel 
1582abb0f93cSkardel #ifdef INCLUDE_IPV6_SUPPORT
1583abb0f93cSkardel 	if (IS_IPV6(psau) && S_ADDR6_EQ(psau, &in6addr_any))
1584abb0f93cSkardel 		return 1;
1585abb0f93cSkardel #endif
1586abb0f93cSkardel 
1587abb0f93cSkardel 	return 0;
1588abb0f93cSkardel }
1589abb0f93cSkardel 
1590abb0f93cSkardel 
1591abb0f93cSkardel #ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND
1592abb0f93cSkardel /*
1593abb0f93cSkardel  * enable/disable re-use of wildcard address socket
1594abb0f93cSkardel  */
1595abb0f93cSkardel static void
set_wildcard_reuse(u_short family,int on)1596abb0f93cSkardel set_wildcard_reuse(
1597abb0f93cSkardel 	u_short	family,
1598abb0f93cSkardel 	int	on
1599abb0f93cSkardel 	)
1600abb0f93cSkardel {
1601abb0f93cSkardel 	struct interface *any;
1602abb0f93cSkardel 	SOCKET fd = INVALID_SOCKET;
1603abb0f93cSkardel 
1604abb0f93cSkardel 	any = ANY_INTERFACE_BYFAM(family);
1605abb0f93cSkardel 	if (any != NULL)
1606abb0f93cSkardel 		fd = any->fd;
1607abb0f93cSkardel 
1608abb0f93cSkardel 	if (fd != INVALID_SOCKET) {
1609abb0f93cSkardel 		if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
1610169394abSchristos 			       (void *)&on, sizeof(on)))
1611abb0f93cSkardel 			msyslog(LOG_ERR,
1612abb0f93cSkardel 				"set_wildcard_reuse: setsockopt(SO_REUSEADDR, %s) failed: %m",
1613abb0f93cSkardel 				on ? "on" : "off");
1614abb0f93cSkardel 
1615abb0f93cSkardel 		DPRINTF(4, ("set SO_REUSEADDR to %s on %s\n",
1616abb0f93cSkardel 			    on ? "on" : "off",
1617abb0f93cSkardel 			    stoa(&any->sin)));
1618abb0f93cSkardel 	}
1619abb0f93cSkardel }
1620abb0f93cSkardel #endif /* OS_NEEDS_REUSEADDR_FOR_IFADDRBIND */
1621abb0f93cSkardel 
16227469785fSroy static isc_boolean_t
check_flags(sockaddr_u * psau,const char * name,u_int32 flags)16237469785fSroy check_flags(
16247469785fSroy 	sockaddr_u *psau,
16257469785fSroy 	const char *name,
16267469785fSroy 	u_int32 flags
16277469785fSroy 	)
16287469785fSroy {
16297469785fSroy #if defined(SIOCGIFAFLAG_IN)
16307469785fSroy 	struct ifreq ifr;
16317469785fSroy 	int fd;
16327469785fSroy 
16337469785fSroy 	if (psau->sa.sa_family != AF_INET)
16347469785fSroy 		return ISC_FALSE;
16357469785fSroy 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
16367469785fSroy 		return ISC_FALSE;
16377469785fSroy 	ZERO(ifr);
16387469785fSroy 	memcpy(&ifr.ifr_addr, &psau->sa, sizeof(ifr.ifr_addr));
16397469785fSroy 	strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
16407469785fSroy 	if (ioctl(fd, SIOCGIFAFLAG_IN, &ifr) < 0) {
16417469785fSroy 		close(fd);
16427469785fSroy 		return ISC_FALSE;
16437469785fSroy 	}
16447469785fSroy 	close(fd);
16457469785fSroy 	if ((ifr.ifr_addrflags & flags) != 0)
16467469785fSroy 		return ISC_TRUE;
16477469785fSroy #endif	/* SIOCGIFAFLAG_IN */
16487469785fSroy 	return ISC_FALSE;
16497469785fSroy }
165045530cf1Skardel 
165145530cf1Skardel static isc_boolean_t
check_flags6(sockaddr_u * psau,const char * name,u_int32 flags6)1652df44c210Sroy check_flags6(
165345530cf1Skardel 	sockaddr_u *psau,
1654df44c210Sroy 	const char *name,
1655df44c210Sroy 	u_int32 flags6
165645530cf1Skardel 	)
165745530cf1Skardel {
1658df44c210Sroy #if defined(INCLUDE_IPV6_SUPPORT) && defined(SIOCGIFAFLAG_IN6)
165945530cf1Skardel 	struct in6_ifreq ifr6;
166045530cf1Skardel 	int fd;
166145530cf1Skardel 
166245530cf1Skardel 	if (psau->sa.sa_family != AF_INET6)
166345530cf1Skardel 		return ISC_FALSE;
166445530cf1Skardel 	if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
166545530cf1Skardel 		return ISC_FALSE;
1666b3d6264cSchristos 	ZERO(ifr6);
166745530cf1Skardel 	memcpy(&ifr6.ifr_addr, &psau->sa6, sizeof(ifr6.ifr_addr));
1668b3d6264cSchristos 	strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
166945530cf1Skardel 	if (ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
167045530cf1Skardel 		close(fd);
167145530cf1Skardel 		return ISC_FALSE;
167245530cf1Skardel 	}
167345530cf1Skardel 	close(fd);
1674df44c210Sroy 	if ((ifr6.ifr_ifru.ifru_flags6 & flags6) != 0)
167545530cf1Skardel 		return ISC_TRUE;
1676df44c210Sroy #endif	/* INCLUDE_IPV6_SUPPORT && SIOCGIFAFLAG_IN6 */
167745530cf1Skardel 	return ISC_FALSE;
167845530cf1Skardel }
167945530cf1Skardel 
1680df44c210Sroy static isc_boolean_t
is_anycast(sockaddr_u * psau,const char * name)1681df44c210Sroy is_anycast(
1682df44c210Sroy 	sockaddr_u *psau,
1683df44c210Sroy 	const char *name
1684df44c210Sroy 	)
1685df44c210Sroy {
1686df44c210Sroy #ifdef IN6_IFF_ANYCAST
1687df44c210Sroy 	return check_flags6(psau, name, IN6_IFF_ANYCAST);
1688df44c210Sroy #else
1689df44c210Sroy 	return ISC_FALSE;
1690df44c210Sroy #endif
1691df44c210Sroy }
1692df44c210Sroy 
1693df44c210Sroy static isc_boolean_t
is_valid(sockaddr_u * psau,const char * name)1694df44c210Sroy is_valid(
1695df44c210Sroy 	sockaddr_u *psau,
1696df44c210Sroy 	const char *name
1697df44c210Sroy 	)
1698df44c210Sroy {
16997469785fSroy 	u_int32 flags;
1700df44c210Sroy 
17017469785fSroy 	flags = 0;
17027469785fSroy 	switch (psau->sa.sa_family) {
17037469785fSroy 	case AF_INET:
17047469785fSroy #ifdef IN_IFF_DETACHED
17057469785fSroy 		flags |= IN_IFF_DETACHED;
17067469785fSroy #endif
17077469785fSroy #ifdef IN_IFF_TENTATIVE
17087469785fSroy 		flags |= IN_IFF_TENTATIVE;
17097469785fSroy #endif
17107469785fSroy 		return check_flags(psau, name, flags) ? ISC_FALSE : ISC_TRUE;
17117469785fSroy 	case AF_INET6:
1712df44c210Sroy #ifdef IN6_IFF_DEPARTED
17137469785fSroy 		flags |= IN6_IFF_DEPARTED;
1714df44c210Sroy #endif
1715df44c210Sroy #ifdef IN6_IFF_DETACHED
17167469785fSroy 		flags |= IN6_IFF_DETACHED;
1717df44c210Sroy #endif
1718df44c210Sroy #ifdef IN6_IFF_TENTATIVE
17197469785fSroy 		flags |= IN6_IFF_TENTATIVE;
1720df44c210Sroy #endif
17217469785fSroy 		return check_flags6(psau, name, flags) ? ISC_FALSE : ISC_TRUE;
17227469785fSroy 	default:
17237469785fSroy 		return ISC_FALSE;
17247469785fSroy 	}
1725df44c210Sroy }
172645530cf1Skardel 
1727abb0f93cSkardel /*
1728abb0f93cSkardel  * update_interface strategy
1729abb0f93cSkardel  *
1730abb0f93cSkardel  * toggle configuration phase
1731abb0f93cSkardel  *
1732abb0f93cSkardel  * Phase 1:
1733abb0f93cSkardel  * forall currently existing interfaces
1734abb0f93cSkardel  *   if address is known:
1735abb0f93cSkardel  *	drop socket - rebind again
1736abb0f93cSkardel  *
1737abb0f93cSkardel  *   if address is NOT known:
1738abb0f93cSkardel  *	attempt to create a new interface entry
1739abb0f93cSkardel  *
1740abb0f93cSkardel  * Phase 2:
1741abb0f93cSkardel  * forall currently known non MCAST and WILDCARD interfaces
1742abb0f93cSkardel  *   if interface does not match configuration phase (not seen in phase 1):
1743abb0f93cSkardel  *	remove interface from known interface list
1744abb0f93cSkardel  *	forall peers associated with this interface
1745abb0f93cSkardel  *         disconnect peer from this interface
1746abb0f93cSkardel  *
1747abb0f93cSkardel  * Phase 3:
1748abb0f93cSkardel  *   attempt to re-assign interfaces to peers
1749abb0f93cSkardel  *
1750abb0f93cSkardel  */
1751abb0f93cSkardel 
1752abb0f93cSkardel static int
update_interfaces(u_short port,interface_receiver_t receiver,void * data)1753abb0f93cSkardel update_interfaces(
1754abb0f93cSkardel 	u_short			port,
1755abb0f93cSkardel 	interface_receiver_t	receiver,
1756abb0f93cSkardel 	void *			data
1757abb0f93cSkardel 	)
1758abb0f93cSkardel {
1759abb0f93cSkardel 	isc_mem_t *		mctx = (void *)-1;
1760abb0f93cSkardel 	interface_info_t	ifi;
1761abb0f93cSkardel 	isc_interfaceiter_t *	iter;
1762abb0f93cSkardel 	isc_result_t		result;
1763abb0f93cSkardel 	isc_interface_t		isc_if;
1764abb0f93cSkardel 	int			new_interface_found;
1765abb0f93cSkardel 	unsigned int		family;
176645530cf1Skardel 	endpt			enumep;
176745530cf1Skardel 	endpt *			ep;
176845530cf1Skardel 	endpt *			next_ep;
1769abb0f93cSkardel 
1770abb0f93cSkardel 	DPRINTF(3, ("update_interfaces(%d)\n", port));
1771abb0f93cSkardel 
1772abb0f93cSkardel 	/*
1773abb0f93cSkardel 	 * phase one - scan interfaces
1774abb0f93cSkardel 	 * - create those that are not found
1775abb0f93cSkardel 	 * - update those that are found
1776abb0f93cSkardel 	 */
1777abb0f93cSkardel 
177845530cf1Skardel 	new_interface_found = FALSE;
1779abb0f93cSkardel 	iter = NULL;
1780abb0f93cSkardel 	result = isc_interfaceiter_create(mctx, &iter);
1781abb0f93cSkardel 
1782abb0f93cSkardel 	if (result != ISC_R_SUCCESS)
1783abb0f93cSkardel 		return 0;
1784abb0f93cSkardel 
1785abb0f93cSkardel 	/*
1786abb0f93cSkardel 	 * Toggle system interface scan phase to find untouched
1787abb0f93cSkardel 	 * interfaces to be deleted.
1788abb0f93cSkardel 	 */
1789abb0f93cSkardel 	sys_interphase ^= 0x1;
1790abb0f93cSkardel 
1791abb0f93cSkardel 	for (result = isc_interfaceiter_first(iter);
1792abb0f93cSkardel 	     ISC_R_SUCCESS == result;
1793abb0f93cSkardel 	     result = isc_interfaceiter_next(iter)) {
1794abb0f93cSkardel 
1795abb0f93cSkardel 		result = isc_interfaceiter_current(iter, &isc_if);
1796abb0f93cSkardel 
1797abb0f93cSkardel 		if (result != ISC_R_SUCCESS)
1798abb0f93cSkardel 			break;
1799abb0f93cSkardel 
1800abb0f93cSkardel 		/* See if we have a valid family to use */
1801abb0f93cSkardel 		family = isc_if.address.family;
1802abb0f93cSkardel 		if (AF_INET != family && AF_INET6 != family)
1803abb0f93cSkardel 			continue;
1804abb0f93cSkardel 		if (AF_INET == family && !ipv4_works)
1805abb0f93cSkardel 			continue;
1806abb0f93cSkardel 		if (AF_INET6 == family && !ipv6_works)
1807abb0f93cSkardel 			continue;
1808abb0f93cSkardel 
1809abb0f93cSkardel 		/* create prototype */
181045530cf1Skardel 		init_interface(&enumep);
1811abb0f93cSkardel 
181245530cf1Skardel 		convert_isc_if(&isc_if, &enumep, port);
1813abb0f93cSkardel 
1814b3d6264cSchristos 		DPRINT_INTERFACE(4, (&enumep, "examining ", "\n"));
1815b3d6264cSchristos 
1816abb0f93cSkardel 		/*
1817abb0f93cSkardel 		 * Check if and how we are going to use the interface.
1818abb0f93cSkardel 		 */
181945530cf1Skardel 		switch (interface_action(enumep.name, &enumep.sin,
182045530cf1Skardel 					 enumep.flags)) {
1821abb0f93cSkardel 
1822abb0f93cSkardel 		case ACTION_IGNORE:
1823b3d6264cSchristos 			DPRINTF(4, ("ignoring interface %s (%s) - by nic rules\n",
1824b3d6264cSchristos 				    enumep.name, stoa(&enumep.sin)));
1825abb0f93cSkardel 			continue;
1826abb0f93cSkardel 
1827abb0f93cSkardel 		case ACTION_LISTEN:
1828b3d6264cSchristos 			DPRINTF(4, ("listen interface %s (%s) - by nic rules\n",
1829b3d6264cSchristos 				    enumep.name, stoa(&enumep.sin)));
183045530cf1Skardel 			enumep.ignore_packets = ISC_FALSE;
1831abb0f93cSkardel 			break;
1832abb0f93cSkardel 
1833abb0f93cSkardel 		case ACTION_DROP:
1834b3d6264cSchristos 			DPRINTF(4, ("drop on interface %s (%s) - by nic rules\n",
1835b3d6264cSchristos 				    enumep.name, stoa(&enumep.sin)));
183645530cf1Skardel 			enumep.ignore_packets = ISC_TRUE;
1837abb0f93cSkardel 			break;
1838abb0f93cSkardel 		}
1839abb0f93cSkardel 
1840abb0f93cSkardel 		 /* interfaces must be UP to be usable */
184145530cf1Skardel 		if (!(enumep.flags & INT_UP)) {
1842abb0f93cSkardel 			DPRINTF(4, ("skipping interface %s (%s) - DOWN\n",
184345530cf1Skardel 				    enumep.name, stoa(&enumep.sin)));
1844abb0f93cSkardel 			continue;
1845abb0f93cSkardel 		}
1846abb0f93cSkardel 
1847abb0f93cSkardel 		/*
1848abb0f93cSkardel 		 * skip any interfaces UP and bound to a wildcard
1849abb0f93cSkardel 		 * address - some dhcp clients produce that in the
1850abb0f93cSkardel 		 * wild
1851abb0f93cSkardel 		 */
185245530cf1Skardel 		if (is_wildcard_addr(&enumep.sin))
185345530cf1Skardel 			continue;
185445530cf1Skardel 
185545530cf1Skardel 		if (is_anycast(&enumep.sin, isc_if.name))
1856abb0f93cSkardel 			continue;
1857abb0f93cSkardel 
1858abb0f93cSkardel 		/*
1859df44c210Sroy 		 * skip any address that is an invalid state to be used
1860df44c210Sroy 		 */
1861df44c210Sroy 		if (!is_valid(&enumep.sin, isc_if.name))
1862df44c210Sroy 			continue;
1863df44c210Sroy 
1864df44c210Sroy 		/*
1865abb0f93cSkardel 		 * map to local *address* in order to map all duplicate
186645530cf1Skardel 		 * interfaces to an endpt structure with the appropriate
186745530cf1Skardel 		 * socket.  Our name space is (ip-address), NOT
186845530cf1Skardel 		 * (interface name, ip-address).
1869abb0f93cSkardel 		 */
187045530cf1Skardel 		ep = getinterface(&enumep.sin, INT_WILDCARD);
1871abb0f93cSkardel 
187245530cf1Skardel 		if (ep != NULL && refresh_interface(ep)) {
1873abb0f93cSkardel 			/*
1874abb0f93cSkardel 			 * found existing and up to date interface -
1875abb0f93cSkardel 			 * mark present.
1876abb0f93cSkardel 			 */
187745530cf1Skardel 			if (ep->phase != sys_interphase) {
1878abb0f93cSkardel 				/*
1879abb0f93cSkardel 				 * On a new round we reset the name so
1880abb0f93cSkardel 				 * the interface name shows up again if
1881abb0f93cSkardel 				 * this address is no longer shared.
188245530cf1Skardel 				 * We reset ignore_packets from the
188345530cf1Skardel 				 * new prototype to respect any runtime
188445530cf1Skardel 				 * changes to the nic rules.
1885abb0f93cSkardel 				 */
1886b3d6264cSchristos 				strlcpy(ep->name, enumep.name,
188745530cf1Skardel 					sizeof(ep->name));
188845530cf1Skardel 				ep->ignore_packets =
188945530cf1Skardel 					    enumep.ignore_packets;
189045530cf1Skardel 			} else {
1891abb0f93cSkardel 				/* name collision - rename interface */
1892b3d6264cSchristos 				strlcpy(ep->name, "*multiple*",
189345530cf1Skardel 					sizeof(ep->name));
189445530cf1Skardel 			}
1895abb0f93cSkardel 
189645530cf1Skardel 			DPRINT_INTERFACE(4, (ep, "updating ",
1897abb0f93cSkardel 					     " present\n"));
1898abb0f93cSkardel 
189945530cf1Skardel 			if (ep->ignore_packets !=
190045530cf1Skardel 			    enumep.ignore_packets) {
1901abb0f93cSkardel 				/*
1902abb0f93cSkardel 				 * We have conflicting configurations
1903abb0f93cSkardel 				 * for the interface address. This is
1904abb0f93cSkardel 				 * caused by using -I <interfacename>
1905abb0f93cSkardel 				 * for an interface that shares its
1906abb0f93cSkardel 				 * address with other interfaces. We
1907abb0f93cSkardel 				 * can not disambiguate incoming
1908abb0f93cSkardel 				 * packets delivered to this socket
1909abb0f93cSkardel 				 * without extra syscalls/features.
1910abb0f93cSkardel 				 * These are not (commonly) available.
1911abb0f93cSkardel 				 * Note this is a more unusual
1912abb0f93cSkardel 				 * configuration where several
1913abb0f93cSkardel 				 * interfaces share an address but
1914abb0f93cSkardel 				 * filtering via interface name is
1915abb0f93cSkardel 				 * attempted.  We resolve the
1916abb0f93cSkardel 				 * configuration conflict by disabling
1917abb0f93cSkardel 				 * the processing of received packets.
1918abb0f93cSkardel 				 * This leads to no service on the
1919abb0f93cSkardel 				 * interface address where the conflict
1920abb0f93cSkardel 				 * occurs.
1921abb0f93cSkardel 				 */
1922abb0f93cSkardel 				msyslog(LOG_ERR,
1923abb0f93cSkardel 					"WARNING: conflicting enable configuration for interfaces %s and %s for address %s - unsupported configuration - address DISABLED",
192445530cf1Skardel 					enumep.name, ep->name,
192545530cf1Skardel 					stoa(&enumep.sin));
1926abb0f93cSkardel 
192745530cf1Skardel 				ep->ignore_packets = ISC_TRUE;
1928abb0f93cSkardel 			}
1929abb0f93cSkardel 
193045530cf1Skardel 			ep->phase = sys_interphase;
1931abb0f93cSkardel 
1932abb0f93cSkardel 			ifi.action = IFS_EXISTS;
193345530cf1Skardel 			ifi.ep = ep;
1934abb0f93cSkardel 			if (receiver != NULL)
1935abb0f93cSkardel 				(*receiver)(data, &ifi);
1936abb0f93cSkardel 		} else {
1937abb0f93cSkardel 			/*
1938abb0f93cSkardel 			 * This is new or refreshing failed - add to
1939abb0f93cSkardel 			 * our interface list.  If refreshing failed we
1940abb0f93cSkardel 			 * will delete the interface structure in phase
1941abb0f93cSkardel 			 * 2 as the interface was not marked current.
1942abb0f93cSkardel 			 * We can bind to the address as the refresh
1943abb0f93cSkardel 			 * code already closed the offending socket
1944abb0f93cSkardel 			 */
194545530cf1Skardel 			ep = create_interface(port, &enumep);
1946abb0f93cSkardel 
194745530cf1Skardel 			if (ep != NULL) {
1948abb0f93cSkardel 				ifi.action = IFS_CREATED;
194945530cf1Skardel 				ifi.ep = ep;
1950abb0f93cSkardel 				if (receiver != NULL)
1951abb0f93cSkardel 					(*receiver)(data, &ifi);
1952abb0f93cSkardel 
195345530cf1Skardel 				new_interface_found = TRUE;
1954abb0f93cSkardel 				DPRINT_INTERFACE(3,
195545530cf1Skardel 					(ep, "updating ",
1956abb0f93cSkardel 					 " new - created\n"));
1957abb0f93cSkardel 			} else {
1958abb0f93cSkardel 				DPRINT_INTERFACE(3,
195945530cf1Skardel 					(&enumep, "updating ",
1960abb0f93cSkardel 					 " new - creation FAILED"));
1961abb0f93cSkardel 
1962abb0f93cSkardel 				msyslog(LOG_INFO,
1963abb0f93cSkardel 					"failed to init interface for address %s",
196445530cf1Skardel 					stoa(&enumep.sin));
1965abb0f93cSkardel 				continue;
1966abb0f93cSkardel 			}
1967abb0f93cSkardel 		}
1968abb0f93cSkardel 	}
1969abb0f93cSkardel 
1970abb0f93cSkardel 	isc_interfaceiter_destroy(&iter);
1971abb0f93cSkardel 
1972abb0f93cSkardel 	/*
1973abb0f93cSkardel 	 * phase 2 - delete gone interfaces - reassigning peers to
1974abb0f93cSkardel 	 * other interfaces
1975abb0f93cSkardel 	 */
197645530cf1Skardel 	for (ep = ep_list; ep != NULL; ep = next_ep) {
197745530cf1Skardel 		next_ep = ep->elink;
1978abb0f93cSkardel 
1979abb0f93cSkardel 		/*
198045530cf1Skardel 		 * if phase does not match sys_phase this interface was
198145530cf1Skardel 		 * not enumerated during the last interface scan - so it
198245530cf1Skardel 		 * is gone and will be deleted here unless it did not
198345530cf1Skardel 		 * originate from interface enumeration (INT_WILDCARD,
198445530cf1Skardel 		 * INT_MCASTIF).
1985abb0f93cSkardel 		 */
198645530cf1Skardel 		if (((INT_WILDCARD | INT_MCASTIF) & ep->flags) ||
198745530cf1Skardel 		    ep->phase == sys_interphase)
198845530cf1Skardel 			continue;
198945530cf1Skardel 
199045530cf1Skardel 		DPRINT_INTERFACE(3, (ep, "updating ",
1991abb0f93cSkardel 				     "GONE - deleting\n"));
199245530cf1Skardel 		remove_interface(ep);
1993abb0f93cSkardel 
1994abb0f93cSkardel 		ifi.action = IFS_DELETED;
199545530cf1Skardel 		ifi.ep = ep;
1996abb0f93cSkardel 		if (receiver != NULL)
1997abb0f93cSkardel 			(*receiver)(data, &ifi);
1998abb0f93cSkardel 
199945530cf1Skardel 		/* disconnect peers from deleted endpt. */
200045530cf1Skardel 		while (ep->peers != NULL)
200145530cf1Skardel 			set_peerdstadr(ep->peers, NULL);
2002abb0f93cSkardel 
2003abb0f93cSkardel 		/*
2004abb0f93cSkardel 		 * update globals in case we lose
2005abb0f93cSkardel 		 * a loopback interface
2006abb0f93cSkardel 		 */
200745530cf1Skardel 		if (ep == loopback_interface)
2008abb0f93cSkardel 			loopback_interface = NULL;
2009abb0f93cSkardel 
201045530cf1Skardel 		delete_interface(ep);
2011abb0f93cSkardel 	}
2012abb0f93cSkardel 
2013abb0f93cSkardel 	/*
2014b3d6264cSchristos 	 * phase 3 - re-configure as the world has possibly changed
2015b3d6264cSchristos 	 *
2016b3d6264cSchristos 	 * never ever make this conditional again - it is needed to track
2017b3d6264cSchristos 	 * routing updates. see bug #2506
2018abb0f93cSkardel 	 */
2019abb0f93cSkardel 	refresh_all_peerinterfaces();
2020b3d6264cSchristos 
20219034ec65Schristos 	if (broadcast_client_enabled || sys_bclient)
2022766d83b9Skardel 		io_setbclient();
2023766d83b9Skardel 
202409f14f80Schristos #ifdef MCAST
20254e3b3909Schristos 	/*
20264e3b3909Schristos 	 * Check multicast interfaces and try to join multicast groups if
20274e3b3909Schristos          * not joined yet.
20284e3b3909Schristos          */
20294e3b3909Schristos 	for (ep = ep_list; ep != NULL; ep = ep->elink) {
20304e3b3909Schristos 		remaddr_t *entry;
20314e3b3909Schristos 
20324e3b3909Schristos 		if (!(INT_MCASTIF & ep->flags) || (INT_MCASTOPEN & ep->flags))
20334e3b3909Schristos 			continue;
20344e3b3909Schristos 
20354e3b3909Schristos 		/* Find remote address that was linked to this interface */
20364e3b3909Schristos 		for (entry = remoteaddr_list;
20374e3b3909Schristos 		     entry != NULL;
20384e3b3909Schristos 		     entry = entry->link) {
20394e3b3909Schristos 			if (entry->ep == ep) {
20404e3b3909Schristos 				if (socket_multicast_enable(ep, &entry->addr)) {
20414e3b3909Schristos 					msyslog(LOG_INFO,
20424e3b3909Schristos 						"Joined %s socket to multicast group %s",
20434e3b3909Schristos 						stoa(&ep->sin),
20444e3b3909Schristos 						stoa(&entry->addr));
20454e3b3909Schristos 				}
20464e3b3909Schristos 				break;
20474e3b3909Schristos 			}
20484e3b3909Schristos 		}
20494e3b3909Schristos 	}
205009f14f80Schristos #endif /* MCAST */
20514e3b3909Schristos 
2052abb0f93cSkardel 	return new_interface_found;
2053abb0f93cSkardel }
2054abb0f93cSkardel 
2055abb0f93cSkardel 
2056abb0f93cSkardel /*
2057abb0f93cSkardel  * create_sockets - create a socket for each interface plus a default
2058abb0f93cSkardel  *			socket for when we don't know where to send
2059abb0f93cSkardel  */
2060abb0f93cSkardel static int
create_sockets(u_short port)2061abb0f93cSkardel create_sockets(
2062abb0f93cSkardel 	u_short port
2063abb0f93cSkardel 	)
2064abb0f93cSkardel {
2065abb0f93cSkardel #ifndef HAVE_IO_COMPLETION_PORT
2066abb0f93cSkardel 	/*
2067abb0f93cSkardel 	 * I/O Completion Ports don't care about the select and FD_SET
2068abb0f93cSkardel 	 */
2069abb0f93cSkardel 	maxactivefd = 0;
2070abb0f93cSkardel 	FD_ZERO(&activefds);
2071abb0f93cSkardel #endif
2072abb0f93cSkardel 
2073abb0f93cSkardel 	DPRINTF(2, ("create_sockets(%d)\n", port));
2074abb0f93cSkardel 
2075abb0f93cSkardel 	create_wildcards(port);
2076abb0f93cSkardel 
2077abb0f93cSkardel 	update_interfaces(port, NULL, NULL);
2078abb0f93cSkardel 
2079abb0f93cSkardel 	/*
2080abb0f93cSkardel 	 * Now that we have opened all the sockets, turn off the reuse
2081abb0f93cSkardel 	 * flag for security.
2082abb0f93cSkardel 	 */
2083abb0f93cSkardel 	set_reuseaddr(0);
2084abb0f93cSkardel 
2085abb0f93cSkardel 	DPRINTF(2, ("create_sockets: Total interfaces = %d\n", ninterfaces));
2086abb0f93cSkardel 
2087abb0f93cSkardel 	return ninterfaces;
2088abb0f93cSkardel }
2089abb0f93cSkardel 
2090abb0f93cSkardel /*
2091abb0f93cSkardel  * create_interface - create a new interface for a given prototype
2092abb0f93cSkardel  *		      binding the socket.
2093abb0f93cSkardel  */
2094abb0f93cSkardel static struct interface *
create_interface(u_short port,struct interface * protot)2095abb0f93cSkardel create_interface(
2096abb0f93cSkardel 	u_short			port,
2097abb0f93cSkardel 	struct interface *	protot
2098abb0f93cSkardel 	)
2099abb0f93cSkardel {
2100abb0f93cSkardel 	sockaddr_u	resmask;
210145530cf1Skardel 	endpt *		iface;
210245530cf1Skardel #if defined(MCAST) && defined(MULTICAST_NONEWSOCKET)
210345530cf1Skardel 	remaddr_t *	entry;
210445530cf1Skardel 	remaddr_t *	next_entry;
210545530cf1Skardel #endif
2106abb0f93cSkardel 	DPRINTF(2, ("create_interface(%s#%d)\n", stoa(&protot->sin),
2107abb0f93cSkardel 		    port));
2108abb0f93cSkardel 
2109abb0f93cSkardel 	/* build an interface */
2110abb0f93cSkardel 	iface = new_interface(protot);
2111abb0f93cSkardel 
2112abb0f93cSkardel 	/*
2113abb0f93cSkardel 	 * create socket
2114abb0f93cSkardel 	 */
2115abb0f93cSkardel 	iface->fd = open_socket(&iface->sin, 0, 0, iface);
2116abb0f93cSkardel 
2117abb0f93cSkardel 	if (iface->fd != INVALID_SOCKET)
211845530cf1Skardel 		log_listen_address(iface);
2119abb0f93cSkardel 
2120abb0f93cSkardel 	if ((INT_BROADCAST & iface->flags)
2121abb0f93cSkardel 	    && iface->bfd != INVALID_SOCKET)
2122abb0f93cSkardel 		msyslog(LOG_INFO, "Listening on broadcast address %s#%d",
2123abb0f93cSkardel 			stoa((&iface->bcast)), port);
2124abb0f93cSkardel 
2125abb0f93cSkardel 	if (INVALID_SOCKET == iface->fd
2126abb0f93cSkardel 	    && INVALID_SOCKET == iface->bfd) {
2127abb0f93cSkardel 		msyslog(LOG_ERR, "unable to create socket on %s (%d) for %s#%d",
2128abb0f93cSkardel 			iface->name,
2129abb0f93cSkardel 			iface->ifnum,
2130abb0f93cSkardel 			stoa((&iface->sin)),
2131abb0f93cSkardel 			port);
2132abb0f93cSkardel 		delete_interface(iface);
2133abb0f93cSkardel 		return NULL;
2134abb0f93cSkardel 	}
2135abb0f93cSkardel 
2136abb0f93cSkardel 	/*
2137abb0f93cSkardel 	 * Blacklist our own addresses, no use talking to ourself
2138abb0f93cSkardel 	 */
2139abb0f93cSkardel 	SET_HOSTMASK(&resmask, AF(&iface->sin));
2140abb0f93cSkardel 	hack_restrict(RESTRICT_FLAGS, &iface->sin, &resmask,
2141169394abSchristos 		      -4, RESM_NTPONLY | RESM_INTERFACE, RES_IGNORE, 0);
2142abb0f93cSkardel 
2143abb0f93cSkardel 	/*
2144abb0f93cSkardel 	 * set globals with the first found
2145abb0f93cSkardel 	 * loopback interface of the appropriate class
2146abb0f93cSkardel 	 */
2147abb0f93cSkardel 	if (NULL == loopback_interface && AF_INET == iface->family
2148abb0f93cSkardel 	    && (INT_LOOPBACK & iface->flags))
2149abb0f93cSkardel 		loopback_interface = iface;
2150abb0f93cSkardel 
2151abb0f93cSkardel 	/*
2152abb0f93cSkardel 	 * put into our interface list
2153abb0f93cSkardel 	 */
2154abb0f93cSkardel 	add_addr_to_list(&iface->sin, iface);
2155abb0f93cSkardel 	add_interface(iface);
2156abb0f93cSkardel 
215745530cf1Skardel #if defined(MCAST) && defined(MULTICAST_NONEWSOCKET)
215845530cf1Skardel 	/*
215945530cf1Skardel 	 * Join any previously-configured compatible multicast groups.
216045530cf1Skardel 	 */
216145530cf1Skardel 	if (INT_MULTICAST & iface->flags &&
216245530cf1Skardel 	    !((INT_LOOPBACK | INT_WILDCARD) & iface->flags) &&
216345530cf1Skardel 	    !iface->ignore_packets) {
216445530cf1Skardel 		for (entry = remoteaddr_list;
216545530cf1Skardel 		     entry != NULL;
216645530cf1Skardel 		     entry = next_entry) {
216745530cf1Skardel 			next_entry = entry->link;
216845530cf1Skardel 			if (AF(&iface->sin) != AF(&entry->addr) ||
216945530cf1Skardel 			    !IS_MCAST(&entry->addr))
217045530cf1Skardel 				continue;
217145530cf1Skardel 			if (socket_multicast_enable(iface,
217245530cf1Skardel 						    &entry->addr))
217345530cf1Skardel 				msyslog(LOG_INFO,
217445530cf1Skardel 					"Joined %s socket to multicast group %s",
217545530cf1Skardel 					stoa(&iface->sin),
217645530cf1Skardel 					stoa(&entry->addr));
217745530cf1Skardel 			else
217845530cf1Skardel 				msyslog(LOG_ERR,
217945530cf1Skardel 					"Failed to join %s socket to multicast group %s",
218045530cf1Skardel 					stoa(&iface->sin),
218145530cf1Skardel 					stoa(&entry->addr));
218245530cf1Skardel 		}
218345530cf1Skardel 	}
218445530cf1Skardel #endif	/* MCAST && MCAST_NONEWSOCKET */
218545530cf1Skardel 
2186abb0f93cSkardel 	DPRINT_INTERFACE(2, (iface, "created ", "\n"));
2187abb0f93cSkardel 	return iface;
2188abb0f93cSkardel }
2189abb0f93cSkardel 
2190abb0f93cSkardel 
2191abb0f93cSkardel #ifdef SO_EXCLUSIVEADDRUSE
2192abb0f93cSkardel static void
set_excladdruse(SOCKET fd)2193abb0f93cSkardel set_excladdruse(
2194abb0f93cSkardel 	SOCKET fd
2195abb0f93cSkardel 	)
2196abb0f93cSkardel {
2197abb0f93cSkardel 	int one = 1;
2198abb0f93cSkardel 	int failed;
2199abb0f93cSkardel #ifdef SYS_WINNT
2200abb0f93cSkardel 	DWORD err;
2201abb0f93cSkardel #endif
2202abb0f93cSkardel 
2203abb0f93cSkardel 	failed = setsockopt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
2204169394abSchristos 			    (void *)&one, sizeof(one));
2205abb0f93cSkardel 
2206abb0f93cSkardel 	if (!failed)
2207abb0f93cSkardel 		return;
2208abb0f93cSkardel 
2209abb0f93cSkardel #ifdef SYS_WINNT
2210abb0f93cSkardel 	/*
2211abb0f93cSkardel 	 * Prior to Windows XP setting SO_EXCLUSIVEADDRUSE can fail with
2212abb0f93cSkardel 	 * error WSAINVAL depending on service pack level and whether
2213abb0f93cSkardel 	 * the user account is in the Administrators group.  Do not
2214abb0f93cSkardel 	 * complain if it fails that way on versions prior to XP (5.1).
2215abb0f93cSkardel 	 */
2216abb0f93cSkardel 	err = GetLastError();
2217abb0f93cSkardel 
2218abb0f93cSkardel 	if (isc_win32os_versioncheck(5, 1, 0, 0) < 0	/* < 5.1/XP */
2219abb0f93cSkardel 	    && WSAEINVAL == err)
2220abb0f93cSkardel 		return;
2221abb0f93cSkardel 
2222abb0f93cSkardel 	SetLastError(err);
2223abb0f93cSkardel #endif
2224abb0f93cSkardel 	msyslog(LOG_ERR,
2225abb0f93cSkardel 		"setsockopt(%d, SO_EXCLUSIVEADDRUSE, on): %m",
2226abb0f93cSkardel 		(int)fd);
2227abb0f93cSkardel }
2228abb0f93cSkardel #endif  /* SO_EXCLUSIVEADDRUSE */
2229abb0f93cSkardel 
2230abb0f93cSkardel 
2231abb0f93cSkardel /*
2232abb0f93cSkardel  * set_reuseaddr() - set/clear REUSEADDR on all sockets
2233abb0f93cSkardel  *			NB possible hole - should we be doing this on broadcast
2234abb0f93cSkardel  *			fd's also?
2235abb0f93cSkardel  */
2236abb0f93cSkardel static void
set_reuseaddr(int flag)2237abb0f93cSkardel set_reuseaddr(
2238abb0f93cSkardel 	int flag
2239abb0f93cSkardel 	)
2240abb0f93cSkardel {
2241abb0f93cSkardel #ifndef SO_EXCLUSIVEADDRUSE
224245530cf1Skardel 	endpt *ep;
2243abb0f93cSkardel 
224445530cf1Skardel 	for (ep = ep_list; ep != NULL; ep = ep->elink) {
224545530cf1Skardel 		if (ep->flags & INT_WILDCARD)
2246abb0f93cSkardel 			continue;
2247abb0f93cSkardel 
2248abb0f93cSkardel 		/*
224945530cf1Skardel 		 * if ep->fd  is INVALID_SOCKET, we might have a adapter
2250abb0f93cSkardel 		 * configured but not present
2251abb0f93cSkardel 		 */
2252abb0f93cSkardel 		DPRINTF(4, ("setting SO_REUSEADDR on %.16s@%s to %s\n",
225345530cf1Skardel 			    ep->name, stoa(&ep->sin),
2254abb0f93cSkardel 			    flag ? "on" : "off"));
2255abb0f93cSkardel 
225645530cf1Skardel 		if (ep->fd != INVALID_SOCKET) {
225745530cf1Skardel 			if (setsockopt(ep->fd, SOL_SOCKET, SO_REUSEADDR,
2258169394abSchristos 				       (void *)&flag, sizeof(flag))) {
225945530cf1Skardel 				msyslog(LOG_ERR, "set_reuseaddr: setsockopt(%s, SO_REUSEADDR, %s) failed: %m",
226045530cf1Skardel 					stoa(&ep->sin), flag ? "on" : "off");
2261abb0f93cSkardel 			}
2262abb0f93cSkardel 		}
2263abb0f93cSkardel 	}
2264abb0f93cSkardel #endif /* ! SO_EXCLUSIVEADDRUSE */
2265abb0f93cSkardel }
2266abb0f93cSkardel 
2267abb0f93cSkardel /*
2268abb0f93cSkardel  * This is just a wrapper around an internal function so we can
2269abb0f93cSkardel  * make other changes as necessary later on
2270abb0f93cSkardel  */
2271abb0f93cSkardel void
enable_broadcast(struct interface * iface,sockaddr_u * baddr)2272abb0f93cSkardel enable_broadcast(
2273abb0f93cSkardel 	struct interface *	iface,
2274abb0f93cSkardel 	sockaddr_u *		baddr
2275abb0f93cSkardel 	)
2276abb0f93cSkardel {
2277abb0f93cSkardel #ifdef OPEN_BCAST_SOCKET
2278abb0f93cSkardel 	socket_broadcast_enable(iface, iface->fd, baddr);
2279abb0f93cSkardel #endif
2280abb0f93cSkardel }
2281abb0f93cSkardel 
2282abb0f93cSkardel #ifdef OPEN_BCAST_SOCKET
2283abb0f93cSkardel /*
2284abb0f93cSkardel  * Enable a broadcast address to a given socket
2285b3d6264cSchristos  * The socket is in the ep_list all we need to do is enable
2286abb0f93cSkardel  * broadcasting. It is not this function's job to select the socket
2287abb0f93cSkardel  */
2288abb0f93cSkardel static isc_boolean_t
socket_broadcast_enable(struct interface * iface,SOCKET fd,sockaddr_u * baddr)2289abb0f93cSkardel socket_broadcast_enable(
2290abb0f93cSkardel 	struct interface *	iface,
2291abb0f93cSkardel 	SOCKET			fd,
2292abb0f93cSkardel 	sockaddr_u *		baddr
2293abb0f93cSkardel 	)
2294abb0f93cSkardel {
2295abb0f93cSkardel #ifdef SO_BROADCAST
2296abb0f93cSkardel 	int on = 1;
2297abb0f93cSkardel 
2298abb0f93cSkardel 	if (IS_IPV4(baddr)) {
2299abb0f93cSkardel 		/* if this interface can support broadcast, set SO_BROADCAST */
2300abb0f93cSkardel 		if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
2301169394abSchristos 			       (void *)&on, sizeof(on)))
2302abb0f93cSkardel 			msyslog(LOG_ERR,
2303abb0f93cSkardel 				"setsockopt(SO_BROADCAST) enable failure on address %s: %m",
2304abb0f93cSkardel 				stoa(baddr));
2305abb0f93cSkardel 		else
2306abb0f93cSkardel 			DPRINTF(2, ("Broadcast enabled on socket %d for address %s\n",
2307abb0f93cSkardel 				    fd, stoa(baddr)));
2308abb0f93cSkardel 	}
2309b3d6264cSchristos 	iface->flags |= INT_BCASTXMIT;
2310abb0f93cSkardel 	return ISC_TRUE;
2311abb0f93cSkardel #else
2312abb0f93cSkardel 	return ISC_FALSE;
2313abb0f93cSkardel #endif /* SO_BROADCAST */
2314abb0f93cSkardel }
2315abb0f93cSkardel 
2316ad131110Schristos #ifdef  OS_MISSES_SPECIFIC_ROUTE_UPDATES
2317abb0f93cSkardel /*
2318abb0f93cSkardel  * Remove a broadcast address from a given socket
2319b3d6264cSchristos  * The socket is in the ep_list all we need to do is disable
2320abb0f93cSkardel  * broadcasting. It is not this function's job to select the socket
2321abb0f93cSkardel  */
2322abb0f93cSkardel static isc_boolean_t
socket_broadcast_disable(struct interface * iface,sockaddr_u * baddr)2323abb0f93cSkardel socket_broadcast_disable(
2324abb0f93cSkardel 	struct interface *	iface,
2325abb0f93cSkardel 	sockaddr_u *		baddr
2326abb0f93cSkardel 	)
2327abb0f93cSkardel {
2328abb0f93cSkardel #ifdef SO_BROADCAST
2329abb0f93cSkardel 	int off = 0;	/* This seems to be OK as an int */
2330abb0f93cSkardel 
2331abb0f93cSkardel 	if (IS_IPV4(baddr) && setsockopt(iface->fd, SOL_SOCKET,
2332169394abSchristos 	    SO_BROADCAST, (void *)&off, sizeof(off)))
2333abb0f93cSkardel 		msyslog(LOG_ERR,
2334abb0f93cSkardel 			"setsockopt(SO_BROADCAST) disable failure on address %s: %m",
2335abb0f93cSkardel 			stoa(baddr));
2336abb0f93cSkardel 
2337b3d6264cSchristos 	iface->flags &= ~INT_BCASTXMIT;
2338abb0f93cSkardel 	return ISC_TRUE;
2339abb0f93cSkardel #else
2340abb0f93cSkardel 	return ISC_FALSE;
2341abb0f93cSkardel #endif /* SO_BROADCAST */
2342abb0f93cSkardel }
2343ad131110Schristos #endif /* OS_MISSES_SPECIFIC_ROUTE_UPDATES */
2344abb0f93cSkardel 
2345abb0f93cSkardel #endif /* OPEN_BCAST_SOCKET */
2346abb0f93cSkardel 
2347abb0f93cSkardel /*
2348abb0f93cSkardel  * return the broadcast client flag value
2349abb0f93cSkardel  */
23509034ec65Schristos /*isc_boolean_t
2351abb0f93cSkardel get_broadcastclient_flag(void)
2352abb0f93cSkardel {
2353abb0f93cSkardel 	return (broadcast_client_enabled);
2354abb0f93cSkardel }
23559034ec65Schristos */
2356335f7552Schristos 
2357abb0f93cSkardel /*
2358abb0f93cSkardel  * Check to see if the address is a multicast address
2359abb0f93cSkardel  */
2360abb0f93cSkardel static isc_boolean_t
addr_ismulticast(sockaddr_u * maddr)2361abb0f93cSkardel addr_ismulticast(
2362abb0f93cSkardel 	sockaddr_u *maddr
2363abb0f93cSkardel 	)
2364abb0f93cSkardel {
2365abb0f93cSkardel 	isc_boolean_t result;
2366abb0f93cSkardel 
2367abb0f93cSkardel #ifndef INCLUDE_IPV6_MULTICAST_SUPPORT
2368abb0f93cSkardel 	/*
2369abb0f93cSkardel 	 * If we don't have IPV6 support any IPV6 addr is not multicast
2370abb0f93cSkardel 	 */
2371abb0f93cSkardel 	if (IS_IPV6(maddr))
2372abb0f93cSkardel 		result = ISC_FALSE;
2373abb0f93cSkardel 	else
2374abb0f93cSkardel #endif
2375abb0f93cSkardel 		result = IS_MCAST(maddr);
2376abb0f93cSkardel 
2377abb0f93cSkardel 	if (!result)
2378abb0f93cSkardel 		DPRINTF(4, ("address %s is not multicast\n",
2379abb0f93cSkardel 			    stoa(maddr)));
2380abb0f93cSkardel 
2381abb0f93cSkardel 	return result;
2382abb0f93cSkardel }
2383abb0f93cSkardel 
2384abb0f93cSkardel /*
2385abb0f93cSkardel  * Multicast servers need to set the appropriate Multicast interface
2386abb0f93cSkardel  * socket option in order for it to know which interface to use for
2387abb0f93cSkardel  * send the multicast packet.
2388abb0f93cSkardel  */
2389abb0f93cSkardel void
enable_multicast_if(struct interface * iface,sockaddr_u * maddr)2390abb0f93cSkardel enable_multicast_if(
2391abb0f93cSkardel 	struct interface *	iface,
2392abb0f93cSkardel 	sockaddr_u *		maddr
2393abb0f93cSkardel 	)
2394abb0f93cSkardel {
2395abb0f93cSkardel #ifdef MCAST
2396b3d6264cSchristos #ifdef IP_MULTICAST_LOOP
2397abb0f93cSkardel 	TYPEOF_IP_MULTICAST_LOOP off = 0;
2398b3d6264cSchristos #endif
239970953dd2Sprlw1 #if defined(INCLUDE_IPV6_MULTICAST_SUPPORT) && defined(IPV6_MULTICAST_LOOP)
2400b3d6264cSchristos 	u_int off6 = 0;
2401b3d6264cSchristos #endif
2402abb0f93cSkardel 
240309f14f80Schristos 	REQUIRE(AF(maddr) == AF(&iface->sin));
2404abb0f93cSkardel 
2405abb0f93cSkardel 	switch (AF(&iface->sin)) {
2406abb0f93cSkardel 
2407abb0f93cSkardel 	case AF_INET:
2408abb0f93cSkardel #ifdef IP_MULTICAST_LOOP
2409abb0f93cSkardel 		/*
2410abb0f93cSkardel 		 * Don't send back to itself, but allow failure to set
2411abb0f93cSkardel 		 */
2412abb0f93cSkardel 		if (setsockopt(iface->fd, IPPROTO_IP,
2413abb0f93cSkardel 			       IP_MULTICAST_LOOP,
2414169394abSchristos 			       (void *)&off,
2415abb0f93cSkardel 			       sizeof(off))) {
2416abb0f93cSkardel 
2417abb0f93cSkardel 			msyslog(LOG_ERR,
2418abb0f93cSkardel 				"setsockopt IP_MULTICAST_LOOP failed: %m on socket %d, addr %s for multicast address %s",
2419abb0f93cSkardel 				iface->fd, stoa(&iface->sin),
2420abb0f93cSkardel 				stoa(maddr));
2421abb0f93cSkardel 		}
2422abb0f93cSkardel #endif
2423abb0f93cSkardel 		break;
2424abb0f93cSkardel 
2425abb0f93cSkardel 	case AF_INET6:
2426abb0f93cSkardel #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
2427abb0f93cSkardel #ifdef IPV6_MULTICAST_LOOP
2428abb0f93cSkardel 		/*
2429abb0f93cSkardel 		 * Don't send back to itself, but allow failure to set
2430abb0f93cSkardel 		 */
2431abb0f93cSkardel 		if (setsockopt(iface->fd, IPPROTO_IPV6,
2432abb0f93cSkardel 			       IPV6_MULTICAST_LOOP,
2433169394abSchristos 			       (void *) &off6, sizeof(off6))) {
2434abb0f93cSkardel 
2435abb0f93cSkardel 			msyslog(LOG_ERR,
2436b3d6264cSchristos 				"setsockopt IPV6_MULTICAST_LOOP failed: %m on socket %d, addr %s for multicast address %s",
2437abb0f93cSkardel 				iface->fd, stoa(&iface->sin),
2438abb0f93cSkardel 				stoa(maddr));
2439abb0f93cSkardel 		}
2440abb0f93cSkardel #endif
2441abb0f93cSkardel 		break;
2442abb0f93cSkardel #else
2443abb0f93cSkardel 		return;
2444abb0f93cSkardel #endif	/* INCLUDE_IPV6_MULTICAST_SUPPORT */
2445abb0f93cSkardel 	}
2446abb0f93cSkardel 	return;
2447abb0f93cSkardel #endif
2448abb0f93cSkardel }
2449abb0f93cSkardel 
2450abb0f93cSkardel /*
2451abb0f93cSkardel  * Add a multicast address to a given socket
2452b3d6264cSchristos  * The socket is in the ep_list all we need to do is enable
2453abb0f93cSkardel  * multicasting. It is not this function's job to select the socket
2454abb0f93cSkardel  */
245545530cf1Skardel #if defined(MCAST)
2456abb0f93cSkardel static isc_boolean_t
socket_multicast_enable(endpt * iface,sockaddr_u * maddr)2457abb0f93cSkardel socket_multicast_enable(
245845530cf1Skardel 	endpt *		iface,
2459abb0f93cSkardel 	sockaddr_u *	maddr
2460abb0f93cSkardel 	)
2461abb0f93cSkardel {
2462abb0f93cSkardel 	struct ip_mreq		mreq;
2463abb0f93cSkardel # ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
2464abb0f93cSkardel 	struct ipv6_mreq	mreq6;
2465abb0f93cSkardel # endif
2466abb0f93cSkardel 	switch (AF(maddr)) {
2467abb0f93cSkardel 
2468abb0f93cSkardel 	case AF_INET:
2469b3d6264cSchristos 		ZERO(mreq);
2470abb0f93cSkardel 		mreq.imr_multiaddr = SOCK_ADDR4(maddr);
2471abb0f93cSkardel 		mreq.imr_interface.s_addr = htonl(INADDR_ANY);
2472abb0f93cSkardel 		if (setsockopt(iface->fd,
2473abb0f93cSkardel 			       IPPROTO_IP,
2474abb0f93cSkardel 			       IP_ADD_MEMBERSHIP,
2475169394abSchristos 			       (void *)&mreq,
2476abb0f93cSkardel 			       sizeof(mreq))) {
24774e3b3909Schristos 			DPRINTF(2, (
2478abb0f93cSkardel 				"setsockopt IP_ADD_MEMBERSHIP failed: %m on socket %d, addr %s for %x / %x (%s)",
2479abb0f93cSkardel 				iface->fd, stoa(&iface->sin),
2480abb0f93cSkardel 				mreq.imr_multiaddr.s_addr,
2481abb0f93cSkardel 				mreq.imr_interface.s_addr,
24824e3b3909Schristos 				stoa(maddr)));
2483abb0f93cSkardel 			return ISC_FALSE;
2484abb0f93cSkardel 		}
2485abb0f93cSkardel 		DPRINTF(4, ("Added IPv4 multicast membership on socket %d, addr %s for %x / %x (%s)\n",
2486abb0f93cSkardel 			    iface->fd, stoa(&iface->sin),
2487abb0f93cSkardel 			    mreq.imr_multiaddr.s_addr,
2488abb0f93cSkardel 			    mreq.imr_interface.s_addr, stoa(maddr)));
2489abb0f93cSkardel 		break;
2490abb0f93cSkardel 
2491abb0f93cSkardel 	case AF_INET6:
2492abb0f93cSkardel # ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
2493abb0f93cSkardel 		/*
2494abb0f93cSkardel 		 * Enable reception of multicast packets.
2495abb0f93cSkardel 		 * If the address is link-local we can get the
2496abb0f93cSkardel 		 * interface index from the scope id. Don't do this
2497abb0f93cSkardel 		 * for other types of multicast addresses. For now let
2498abb0f93cSkardel 		 * the kernel figure it out.
2499abb0f93cSkardel 		 */
2500b3d6264cSchristos 		ZERO(mreq6);
2501abb0f93cSkardel 		mreq6.ipv6mr_multiaddr = SOCK_ADDR6(maddr);
250245530cf1Skardel 		mreq6.ipv6mr_interface = iface->ifindex;
2503abb0f93cSkardel 
2504abb0f93cSkardel 		if (setsockopt(iface->fd, IPPROTO_IPV6,
2505169394abSchristos 			       IPV6_JOIN_GROUP, (void *)&mreq6,
2506abb0f93cSkardel 			       sizeof(mreq6))) {
25074e3b3909Schristos 			DPRINTF(2, (
250845530cf1Skardel 				"setsockopt IPV6_JOIN_GROUP failed: %m on socket %d, addr %s for interface %u (%s)",
2509abb0f93cSkardel 				iface->fd, stoa(&iface->sin),
25104e3b3909Schristos 				mreq6.ipv6mr_interface, stoa(maddr)));
2511abb0f93cSkardel 			return ISC_FALSE;
2512abb0f93cSkardel 		}
251345530cf1Skardel 		DPRINTF(4, ("Added IPv6 multicast group on socket %d, addr %s for interface %u (%s)\n",
2514abb0f93cSkardel 			    iface->fd, stoa(&iface->sin),
2515abb0f93cSkardel 			    mreq6.ipv6mr_interface, stoa(maddr)));
2516abb0f93cSkardel # else
2517abb0f93cSkardel 		return ISC_FALSE;
2518abb0f93cSkardel # endif	/* INCLUDE_IPV6_MULTICAST_SUPPORT */
2519abb0f93cSkardel 	}
2520abb0f93cSkardel 	iface->flags |= INT_MCASTOPEN;
2521abb0f93cSkardel 	iface->num_mcast++;
252245530cf1Skardel 
2523abb0f93cSkardel 	return ISC_TRUE;
2524abb0f93cSkardel }
252545530cf1Skardel #endif	/* MCAST */
252645530cf1Skardel 
2527abb0f93cSkardel 
2528abb0f93cSkardel /*
2529abb0f93cSkardel  * Remove a multicast address from a given socket
2530b3d6264cSchristos  * The socket is in the ep_list all we need to do is disable
2531abb0f93cSkardel  * multicasting. It is not this function's job to select the socket
2532abb0f93cSkardel  */
253345530cf1Skardel #ifdef MCAST
2534abb0f93cSkardel static isc_boolean_t
socket_multicast_disable(struct interface * iface,sockaddr_u * maddr)2535abb0f93cSkardel socket_multicast_disable(
2536abb0f93cSkardel 	struct interface *	iface,
2537abb0f93cSkardel 	sockaddr_u *		maddr
2538abb0f93cSkardel 	)
2539abb0f93cSkardel {
2540abb0f93cSkardel # ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
2541abb0f93cSkardel 	struct ipv6_mreq mreq6;
2542abb0f93cSkardel # endif
2543abb0f93cSkardel 	struct ip_mreq mreq;
2544abb0f93cSkardel 
2545b3d6264cSchristos 	ZERO(mreq);
2546abb0f93cSkardel 
2547abb0f93cSkardel 	if (find_addr_in_list(maddr) == NULL) {
2548abb0f93cSkardel 		DPRINTF(4, ("socket_multicast_disable(%s): not found\n",
2549abb0f93cSkardel 			    stoa(maddr)));
2550abb0f93cSkardel 		return ISC_TRUE;
2551abb0f93cSkardel 	}
2552abb0f93cSkardel 
2553abb0f93cSkardel 	switch (AF(maddr)) {
2554abb0f93cSkardel 
2555abb0f93cSkardel 	case AF_INET:
2556abb0f93cSkardel 		mreq.imr_multiaddr = SOCK_ADDR4(maddr);
2557abb0f93cSkardel 		mreq.imr_interface = SOCK_ADDR4(&iface->sin);
2558abb0f93cSkardel 		if (setsockopt(iface->fd, IPPROTO_IP,
2559169394abSchristos 			       IP_DROP_MEMBERSHIP, (void *)&mreq,
2560abb0f93cSkardel 			       sizeof(mreq))) {
2561abb0f93cSkardel 
2562abb0f93cSkardel 			msyslog(LOG_ERR,
2563abb0f93cSkardel 				"setsockopt IP_DROP_MEMBERSHIP failed: %m on socket %d, addr %s for %x / %x (%s)",
2564abb0f93cSkardel 				iface->fd, stoa(&iface->sin),
2565abb0f93cSkardel 				SRCADR(maddr), SRCADR(&iface->sin),
2566abb0f93cSkardel 				stoa(maddr));
2567abb0f93cSkardel 			return ISC_FALSE;
2568abb0f93cSkardel 		}
2569abb0f93cSkardel 		break;
2570abb0f93cSkardel 	case AF_INET6:
2571abb0f93cSkardel # ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
2572abb0f93cSkardel 		/*
2573abb0f93cSkardel 		 * Disable reception of multicast packets
2574abb0f93cSkardel 		 * If the address is link-local we can get the
2575abb0f93cSkardel 		 * interface index from the scope id.  Don't do this
2576abb0f93cSkardel 		 * for other types of multicast addresses. For now let
2577abb0f93cSkardel 		 * the kernel figure it out.
2578abb0f93cSkardel 		 */
2579abb0f93cSkardel 		mreq6.ipv6mr_multiaddr = SOCK_ADDR6(maddr);
258045530cf1Skardel 		mreq6.ipv6mr_interface = iface->ifindex;
2581abb0f93cSkardel 
2582abb0f93cSkardel 		if (setsockopt(iface->fd, IPPROTO_IPV6,
2583169394abSchristos 			       IPV6_LEAVE_GROUP, (void *)&mreq6,
2584abb0f93cSkardel 			       sizeof(mreq6))) {
2585abb0f93cSkardel 
2586abb0f93cSkardel 			msyslog(LOG_ERR,
2587abb0f93cSkardel 				"setsockopt IPV6_LEAVE_GROUP failure: %m on socket %d, addr %s for %d (%s)",
2588abb0f93cSkardel 				iface->fd, stoa(&iface->sin),
258945530cf1Skardel 				iface->ifindex, stoa(maddr));
2590abb0f93cSkardel 			return ISC_FALSE;
2591abb0f93cSkardel 		}
2592abb0f93cSkardel 		break;
2593abb0f93cSkardel # else
2594abb0f93cSkardel 		return ISC_FALSE;
2595abb0f93cSkardel # endif	/* INCLUDE_IPV6_MULTICAST_SUPPORT */
2596abb0f93cSkardel 	}
2597abb0f93cSkardel 
2598abb0f93cSkardel 	iface->num_mcast--;
2599abb0f93cSkardel 	if (!iface->num_mcast)
2600abb0f93cSkardel 		iface->flags &= ~INT_MCASTOPEN;
2601abb0f93cSkardel 
2602abb0f93cSkardel 	return ISC_TRUE;
2603abb0f93cSkardel }
2604abb0f93cSkardel #endif	/* MCAST */
2605abb0f93cSkardel 
2606abb0f93cSkardel /*
2607abb0f93cSkardel  * io_setbclient - open the broadcast client sockets
2608abb0f93cSkardel  */
2609abb0f93cSkardel void
io_setbclient(void)2610abb0f93cSkardel io_setbclient(void)
2611abb0f93cSkardel {
2612abb0f93cSkardel #ifdef OPEN_BCAST_SOCKET
26139034ec65Schristos 	endpt *		ep;
26149034ec65Schristos 	unsigned int	nif, ni4, ni6;
2615abb0f93cSkardel 
26169034ec65Schristos 	nif = ni4 = ni6 = 0;
2617abb0f93cSkardel 	set_reuseaddr(1);
2618abb0f93cSkardel 
26199034ec65Schristos 	for (ep = ep_list; ep != NULL; ep = ep->elink) {
26209034ec65Schristos 		/* count IPv6 vs IPv4 interfaces. Needed later to decide
26219034ec65Schristos 		 * if we should log an error or not.
26229034ec65Schristos 		 */
26239034ec65Schristos 		switch (ep->family) {
26249034ec65Schristos 		case AF_INET : ++ni4; break;
26259034ec65Schristos 		case AF_INET6: ++ni6; break;
26269034ec65Schristos 		default      :        break;
26279034ec65Schristos 		}
2628abb0f93cSkardel 
26299034ec65Schristos 		if (ep->flags & (INT_WILDCARD | INT_LOOPBACK))
2630abb0f93cSkardel 			continue;
2631abb0f93cSkardel 
2632abb0f93cSkardel 		/* use only allowed addresses */
26339034ec65Schristos 		if (ep->ignore_packets)
2634abb0f93cSkardel 			continue;
2635abb0f93cSkardel 
2636abb0f93cSkardel 		/* Need a broadcast-capable interface */
26379034ec65Schristos 		if (!(ep->flags & INT_BROADCAST))
2638abb0f93cSkardel 			continue;
2639abb0f93cSkardel 
2640abb0f93cSkardel 		/* Only IPv4 addresses are valid for broadcast */
26419034ec65Schristos 		REQUIRE(IS_IPV4(&ep->bcast));
2642abb0f93cSkardel 
2643abb0f93cSkardel 		/* Do we already have the broadcast address open? */
26449034ec65Schristos 		if (ep->flags & INT_BCASTOPEN) {
2645abb0f93cSkardel 			/*
2646abb0f93cSkardel 			 * account for already open interfaces to avoid
2647abb0f93cSkardel 			 * misleading warning below
2648abb0f93cSkardel 			 */
2649abb0f93cSkardel 			nif++;
2650abb0f93cSkardel 			continue;
2651abb0f93cSkardel 		}
2652abb0f93cSkardel 
2653abb0f93cSkardel 		/*
2654abb0f93cSkardel 		 * Try to open the broadcast address
2655abb0f93cSkardel 		 */
26569034ec65Schristos 		ep->family = AF_INET;
26579034ec65Schristos 		ep->bfd = open_socket(&ep->bcast, 1, 0, ep);
2658abb0f93cSkardel 
2659abb0f93cSkardel 		/*
2660abb0f93cSkardel 		 * If we succeeded then we use it otherwise enable
2661abb0f93cSkardel 		 * broadcast on the interface address
2662abb0f93cSkardel 		 */
26639034ec65Schristos 		if (ep->bfd != INVALID_SOCKET) {
2664abb0f93cSkardel 			nif++;
26659034ec65Schristos 			ep->flags |= INT_BCASTOPEN;
2666abb0f93cSkardel 			msyslog(LOG_INFO,
2667b3d6264cSchristos 				"Listen for broadcasts to %s on interface #%d %s",
26689034ec65Schristos 				stoa(&ep->bcast), ep->ifnum, ep->name);
2669335f7552Schristos 		} else switch (errno) {
2670335f7552Schristos 			/* Silently ignore EADDRINUSE as we probably
2671335f7552Schristos 			 * opened the socket already for an address in
2672335f7552Schristos 			 * the same network */
2673335f7552Schristos 		case EADDRINUSE:
2674335f7552Schristos 			/* Some systems cannot bind a socket to a broadcast
2675335f7552Schristos 			 * address, as that is not a valid host address. */
2676335f7552Schristos 		case EADDRNOTAVAIL:
2677335f7552Schristos #		    ifdef SYS_WINNT	/*TODO: use for other systems, too? */
2678335f7552Schristos 			/* avoid recurrence here -- if we already have a
2679335f7552Schristos 			 * regular socket, it's quite useless to try this
2680335f7552Schristos 			 * again.
2681335f7552Schristos 			 */
26829034ec65Schristos 			if (ep->fd != INVALID_SOCKET) {
26839034ec65Schristos 				ep->flags |= INT_BCASTOPEN;
2684335f7552Schristos 				nif++;
2685335f7552Schristos 			}
2686335f7552Schristos #		    endif
2687335f7552Schristos 			break;
2688335f7552Schristos 
2689335f7552Schristos 		default:
2690b3d6264cSchristos 			msyslog(LOG_INFO,
2691b3d6264cSchristos 				"failed to listen for broadcasts to %s on interface #%d %s",
26929034ec65Schristos 				stoa(&ep->bcast), ep->ifnum, ep->name);
2693335f7552Schristos 			break;
2694abb0f93cSkardel 		}
2695abb0f93cSkardel 	}
2696abb0f93cSkardel 	set_reuseaddr(0);
26971c24ec91Schristos 	if (nif != 0) {
2698b3d6264cSchristos 		broadcast_client_enabled = ISC_TRUE;
2699b3d6264cSchristos 		DPRINTF(1, ("io_setbclient: listening to %d broadcast addresses\n", nif));
27001c24ec91Schristos 	} else {
2701b3d6264cSchristos 		broadcast_client_enabled = ISC_FALSE;
27029034ec65Schristos 		/* This is expected when having only IPv6 interfaces
27039034ec65Schristos 		 * and no IPv4 interfaces at all. We suppress the error
27049034ec65Schristos 		 * log in that case... everything else should work!
27059034ec65Schristos 		 */
27069034ec65Schristos 		if (ni4 && !ni6) {
2707abb0f93cSkardel 			msyslog(LOG_ERR,
2708abb0f93cSkardel 				"Unable to listen for broadcasts, no broadcast interfaces available");
2709b3d6264cSchristos 		}
27109034ec65Schristos 	}
2711abb0f93cSkardel #else
2712abb0f93cSkardel 	msyslog(LOG_ERR,
2713abb0f93cSkardel 		"io_setbclient: Broadcast Client disabled by build");
2714abb0f93cSkardel #endif	/* OPEN_BCAST_SOCKET */
2715abb0f93cSkardel }
2716abb0f93cSkardel 
2717abb0f93cSkardel /*
2718abb0f93cSkardel  * io_unsetbclient - close the broadcast client sockets
2719abb0f93cSkardel  */
2720abb0f93cSkardel void
io_unsetbclient(void)2721abb0f93cSkardel io_unsetbclient(void)
2722abb0f93cSkardel {
272345530cf1Skardel 	endpt *ep;
2724abb0f93cSkardel 
272545530cf1Skardel 	for (ep = ep_list; ep != NULL; ep = ep->elink) {
272645530cf1Skardel 		if (INT_WILDCARD & ep->flags)
2727abb0f93cSkardel 			continue;
272845530cf1Skardel 		if (!(INT_BCASTOPEN & ep->flags))
2729abb0f93cSkardel 			continue;
2730b3d6264cSchristos 
2731b3d6264cSchristos 		if (ep->bfd != INVALID_SOCKET) {
2732b3d6264cSchristos 			/* destroy broadcast listening socket */
2733b3d6264cSchristos 			msyslog(LOG_INFO,
2734b3d6264cSchristos 				"stop listening for broadcasts to %s on interface #%d %s",
2735b3d6264cSchristos 				stoa(&ep->bcast), ep->ifnum, ep->name);
2736335f7552Schristos #		    ifdef HAVE_IO_COMPLETION_PORT
2737335f7552Schristos 			io_completion_port_remove_socket(ep->bfd, ep);
2738335f7552Schristos #		    endif
2739b3d6264cSchristos 			close_and_delete_fd_from_list(ep->bfd);
2740b3d6264cSchristos 			ep->bfd = INVALID_SOCKET;
2741abb0f93cSkardel 		}
2742335f7552Schristos 		ep->flags &= ~INT_BCASTOPEN;
2743abb0f93cSkardel 	}
2744b3d6264cSchristos 	broadcast_client_enabled = ISC_FALSE;
2745b3d6264cSchristos }
2746abb0f93cSkardel 
2747abb0f93cSkardel /*
2748abb0f93cSkardel  * io_multicast_add() - add multicast group address
2749abb0f93cSkardel  */
2750abb0f93cSkardel void
io_multicast_add(sockaddr_u * addr)2751abb0f93cSkardel io_multicast_add(
2752abb0f93cSkardel 	sockaddr_u *addr
2753abb0f93cSkardel 	)
2754abb0f93cSkardel {
2755abb0f93cSkardel #ifdef MCAST
275645530cf1Skardel 	endpt *	ep;
275745530cf1Skardel 	endpt *	one_ep;
2758abb0f93cSkardel 
2759abb0f93cSkardel 	/*
2760abb0f93cSkardel 	 * Check to see if this is a multicast address
2761abb0f93cSkardel 	 */
2762abb0f93cSkardel 	if (!addr_ismulticast(addr))
2763abb0f93cSkardel 		return;
2764abb0f93cSkardel 
2765abb0f93cSkardel 	/* If we already have it we can just return */
2766abb0f93cSkardel 	if (NULL != find_flagged_addr_in_list(addr, INT_MCASTOPEN)) {
2767abb0f93cSkardel 		msyslog(LOG_INFO,
2768abb0f93cSkardel 			"Duplicate request found for multicast address %s",
2769abb0f93cSkardel 			stoa(addr));
2770abb0f93cSkardel 		return;
2771abb0f93cSkardel 	}
2772abb0f93cSkardel 
2773abb0f93cSkardel # ifndef MULTICAST_NONEWSOCKET
277445530cf1Skardel 	ep = new_interface(NULL);
2775abb0f93cSkardel 
2776abb0f93cSkardel 	/*
2777abb0f93cSkardel 	 * Open a new socket for the multicast address
2778abb0f93cSkardel 	 */
277945530cf1Skardel 	ep->sin = *addr;
278045530cf1Skardel 	SET_PORT(&ep->sin, NTP_PORT);
278145530cf1Skardel 	ep->family = AF(&ep->sin);
278245530cf1Skardel 	AF(&ep->mask) = ep->family;
278345530cf1Skardel 	SET_ONESMASK(&ep->mask);
2784abb0f93cSkardel 
2785abb0f93cSkardel 	set_reuseaddr(1);
278645530cf1Skardel 	ep->bfd = INVALID_SOCKET;
278745530cf1Skardel 	ep->fd = open_socket(&ep->sin, 0, 0, ep);
278845530cf1Skardel 	if (ep->fd != INVALID_SOCKET) {
278945530cf1Skardel 		ep->ignore_packets = ISC_FALSE;
279045530cf1Skardel 		ep->flags |= INT_MCASTIF;
2791169394abSchristos 		ep->ifindex = SCOPE(addr);
2792abb0f93cSkardel 
2793b3d6264cSchristos 		strlcpy(ep->name, "multicast", sizeof(ep->name));
279445530cf1Skardel 		DPRINT_INTERFACE(2, (ep, "multicast add ", "\n"));
279545530cf1Skardel 		add_interface(ep);
279645530cf1Skardel 		log_listen_address(ep);
2797abb0f93cSkardel 	} else {
2798abb0f93cSkardel 		/* bind failed, re-use wildcard interface */
279945530cf1Skardel 		delete_interface(ep);
2800abb0f93cSkardel 
2801abb0f93cSkardel 		if (IS_IPV4(addr))
280245530cf1Skardel 			ep = wildipv4;
2803abb0f93cSkardel 		else if (IS_IPV6(addr))
280445530cf1Skardel 			ep = wildipv6;
2805abb0f93cSkardel 		else
280645530cf1Skardel 			ep = NULL;
2807abb0f93cSkardel 
280845530cf1Skardel 		if (ep != NULL) {
2809abb0f93cSkardel 			/* HACK ! -- stuff in an address */
2810abb0f93cSkardel 			/* because we don't bind addr? DH */
281145530cf1Skardel 			ep->bcast = *addr;
2812abb0f93cSkardel 			msyslog(LOG_ERR,
2813abb0f93cSkardel 				"multicast address %s using wildcard interface #%d %s",
281445530cf1Skardel 				stoa(addr), ep->ifnum, ep->name);
2815abb0f93cSkardel 		} else {
2816abb0f93cSkardel 			msyslog(LOG_ERR,
2817abb0f93cSkardel 				"No multicast socket available to use for address %s",
2818abb0f93cSkardel 				stoa(addr));
2819abb0f93cSkardel 			return;
2820abb0f93cSkardel 		}
2821abb0f93cSkardel 	}
282245530cf1Skardel 	{	/* in place of the { following for in #else clause */
282345530cf1Skardel 		one_ep = ep;
282445530cf1Skardel # else	/* MULTICAST_NONEWSOCKET follows */
2825abb0f93cSkardel 	/*
282645530cf1Skardel 	 * For the case where we can't use a separate socket (Windows)
282745530cf1Skardel 	 * join each applicable endpoint socket to the group address.
2828abb0f93cSkardel 	 */
282945530cf1Skardel 	if (IS_IPV4(addr))
283045530cf1Skardel 		one_ep = wildipv4;
283145530cf1Skardel 	else
283245530cf1Skardel 		one_ep = wildipv6;
283345530cf1Skardel 	for (ep = ep_list; ep != NULL; ep = ep->elink) {
283445530cf1Skardel 		if (ep->ignore_packets || AF(&ep->sin) != AF(addr) ||
283545530cf1Skardel 		    !(INT_MULTICAST & ep->flags) ||
283645530cf1Skardel 		    (INT_LOOPBACK | INT_WILDCARD) & ep->flags)
283745530cf1Skardel 			continue;
283845530cf1Skardel 		one_ep = ep;
283945530cf1Skardel # endif	/* MULTICAST_NONEWSOCKET */
284045530cf1Skardel 		if (socket_multicast_enable(ep, addr))
284145530cf1Skardel 			msyslog(LOG_INFO,
284245530cf1Skardel 				"Joined %s socket to multicast group %s",
284345530cf1Skardel 				stoa(&ep->sin),
2844abb0f93cSkardel 				stoa(addr));
2845abb0f93cSkardel 	}
2846abb0f93cSkardel 
284745530cf1Skardel 	add_addr_to_list(addr, one_ep);
284845530cf1Skardel #else	/* !MCAST  follows*/
2849abb0f93cSkardel 	msyslog(LOG_ERR,
2850abb0f93cSkardel 		"Can not add multicast address %s: no multicast support",
2851abb0f93cSkardel 		stoa(addr));
285245530cf1Skardel #endif
2853abb0f93cSkardel 	return;
2854abb0f93cSkardel }
2855abb0f93cSkardel 
2856abb0f93cSkardel 
2857abb0f93cSkardel /*
2858abb0f93cSkardel  * io_multicast_del() - delete multicast group address
2859abb0f93cSkardel  */
2860abb0f93cSkardel void
2861abb0f93cSkardel io_multicast_del(
2862abb0f93cSkardel 	sockaddr_u *	addr
2863abb0f93cSkardel 	)
2864abb0f93cSkardel {
2865abb0f93cSkardel #ifdef MCAST
286645530cf1Skardel 	endpt *iface;
2867abb0f93cSkardel 
2868abb0f93cSkardel 	/*
2869abb0f93cSkardel 	 * Check to see if this is a multicast address
2870abb0f93cSkardel 	 */
2871abb0f93cSkardel 	if (!addr_ismulticast(addr)) {
2872abb0f93cSkardel 		msyslog(LOG_ERR, "invalid multicast address %s",
2873abb0f93cSkardel 			stoa(addr));
2874abb0f93cSkardel 		return;
2875abb0f93cSkardel 	}
2876abb0f93cSkardel 
2877abb0f93cSkardel 	/*
2878abb0f93cSkardel 	 * Disable reception of multicast packets
2879abb0f93cSkardel 	 */
2880abb0f93cSkardel 	while ((iface = find_flagged_addr_in_list(addr, INT_MCASTOPEN))
2881abb0f93cSkardel 	       != NULL)
2882abb0f93cSkardel 		socket_multicast_disable(iface, addr);
2883abb0f93cSkardel 
2884abb0f93cSkardel 	delete_addr_from_list(addr);
2885abb0f93cSkardel 
2886abb0f93cSkardel #else /* not MCAST */
2887abb0f93cSkardel 	msyslog(LOG_ERR,
2888abb0f93cSkardel 		"Can not delete multicast address %s: no multicast support",
2889abb0f93cSkardel 		stoa(addr));
2890abb0f93cSkardel #endif /* not MCAST */
2891abb0f93cSkardel }
2892abb0f93cSkardel 
2893abb0f93cSkardel 
2894abb0f93cSkardel /*
2895abb0f93cSkardel  * open_socket - open a socket, returning the file descriptor
2896abb0f93cSkardel  */
2897abb0f93cSkardel 
2898abb0f93cSkardel static SOCKET
2899abb0f93cSkardel open_socket(
2900abb0f93cSkardel 	sockaddr_u *	addr,
2901abb0f93cSkardel 	int		bcast,
2902abb0f93cSkardel 	int		turn_off_reuse,
290345530cf1Skardel 	endpt *		interf
2904abb0f93cSkardel 	)
2905abb0f93cSkardel {
2906abb0f93cSkardel 	SOCKET	fd;
2907abb0f93cSkardel 	int	errval;
2908abb0f93cSkardel 	/*
2909abb0f93cSkardel 	 * int is OK for REUSEADR per
2910abb0f93cSkardel 	 * http://www.kohala.com/start/mcast.api.txt
2911abb0f93cSkardel 	 */
2912abb0f93cSkardel 	int	on = 1;
2913abb0f93cSkardel 	int	off = 0;
2914abb0f93cSkardel 
2915abb0f93cSkardel 	if (IS_IPV6(addr) && !ipv6_works)
2916abb0f93cSkardel 		return INVALID_SOCKET;
2917abb0f93cSkardel 
2918abb0f93cSkardel 	/* create a datagram (UDP) socket */
2919abb0f93cSkardel 	fd = socket(AF(addr), SOCK_DGRAM, 0);
2920abb0f93cSkardel 	if (INVALID_SOCKET == fd) {
292145530cf1Skardel 		errval = socket_errno();
2922abb0f93cSkardel 		msyslog(LOG_ERR,
2923abb0f93cSkardel 			"socket(AF_INET%s, SOCK_DGRAM, 0) failed on address %s: %m",
2924abb0f93cSkardel 			IS_IPV6(addr) ? "6" : "", stoa(addr));
2925abb0f93cSkardel 
2926abb0f93cSkardel 		if (errval == EPROTONOSUPPORT ||
2927abb0f93cSkardel 		    errval == EAFNOSUPPORT ||
2928abb0f93cSkardel 		    errval == EPFNOSUPPORT)
2929abb0f93cSkardel 			return (INVALID_SOCKET);
2930abb0f93cSkardel 
2931abb0f93cSkardel 		errno = errval;
2932abb0f93cSkardel 		msyslog(LOG_ERR,
2933abb0f93cSkardel 			"unexpected socket() error %m code %d (not EPROTONOSUPPORT nor EAFNOSUPPORT nor EPFNOSUPPORT) - exiting",
2934abb0f93cSkardel 			errno);
2935abb0f93cSkardel 		exit(1);
2936abb0f93cSkardel 	}
2937abb0f93cSkardel 
2938abb0f93cSkardel #ifdef SYS_WINNT
2939abb0f93cSkardel 	connection_reset_fix(fd, addr);
2940abb0f93cSkardel #endif
2941abb0f93cSkardel 	/*
2942abb0f93cSkardel 	 * Fixup the file descriptor for some systems
2943abb0f93cSkardel 	 * See bug #530 for details of the issue.
2944abb0f93cSkardel 	 */
2945abb0f93cSkardel 	fd = move_fd(fd);
2946abb0f93cSkardel 
2947abb0f93cSkardel 	/*
2948abb0f93cSkardel 	 * set SO_REUSEADDR since we will be binding the same port
2949abb0f93cSkardel 	 * number on each interface according to turn_off_reuse.
2950abb0f93cSkardel 	 * This is undesirable on Windows versions starting with
2951abb0f93cSkardel 	 * Windows XP (numeric version 5.1).
2952abb0f93cSkardel 	 */
2953abb0f93cSkardel #ifdef SYS_WINNT
2954abb0f93cSkardel 	if (isc_win32os_versioncheck(5, 1, 0, 0) < 0)  /* before 5.1 */
2955abb0f93cSkardel #endif
2956abb0f93cSkardel 		if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
2957169394abSchristos 			       (void *)((turn_off_reuse)
2958abb0f93cSkardel 					    ? &off
2959abb0f93cSkardel 					    : &on),
2960abb0f93cSkardel 			       sizeof(on))) {
2961abb0f93cSkardel 
2962abb0f93cSkardel 			msyslog(LOG_ERR,
2963abb0f93cSkardel 				"setsockopt SO_REUSEADDR %s fails for address %s: %m",
2964abb0f93cSkardel 				(turn_off_reuse)
2965abb0f93cSkardel 				    ? "off"
2966abb0f93cSkardel 				    : "on",
2967abb0f93cSkardel 				stoa(addr));
2968abb0f93cSkardel 			closesocket(fd);
2969abb0f93cSkardel 			return INVALID_SOCKET;
2970abb0f93cSkardel 		}
2971abb0f93cSkardel #ifdef SO_EXCLUSIVEADDRUSE
2972abb0f93cSkardel 	/*
2973abb0f93cSkardel 	 * setting SO_EXCLUSIVEADDRUSE on the wildcard we open
2974abb0f93cSkardel 	 * first will cause more specific binds to fail.
2975abb0f93cSkardel 	 */
2976abb0f93cSkardel 	if (!(interf->flags & INT_WILDCARD))
2977abb0f93cSkardel 		set_excladdruse(fd);
2978abb0f93cSkardel #endif
2979abb0f93cSkardel 
2980abb0f93cSkardel 	/*
2981abb0f93cSkardel 	 * IPv4 specific options go here
2982abb0f93cSkardel 	 */
2983abb0f93cSkardel 	if (IS_IPV4(addr)) {
2984b3d6264cSchristos #if defined(IPPROTO_IP) && defined(IP_TOS)
2985169394abSchristos 		if (setsockopt(fd, IPPROTO_IP, IP_TOS, (void *)&qos,
2986abb0f93cSkardel 			       sizeof(qos)))
2987abb0f93cSkardel 			msyslog(LOG_ERR,
2988abb0f93cSkardel 				"setsockopt IP_TOS (%02x) fails on address %s: %m",
2989abb0f93cSkardel 				qos, stoa(addr));
2990b3d6264cSchristos #endif /* IPPROTO_IP && IP_TOS */
2991abb0f93cSkardel 		if (bcast)
2992abb0f93cSkardel 			socket_broadcast_enable(interf, fd, addr);
2993abb0f93cSkardel 	}
2994abb0f93cSkardel 
2995abb0f93cSkardel 	/*
2996abb0f93cSkardel 	 * IPv6 specific options go here
2997abb0f93cSkardel 	 */
2998abb0f93cSkardel 	if (IS_IPV6(addr)) {
2999b3d6264cSchristos #if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS)
3000169394abSchristos 		if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, (void *)&qos,
3001b3d6264cSchristos 			       sizeof(qos)))
3002b3d6264cSchristos 			msyslog(LOG_ERR,
3003b3d6264cSchristos 				"setsockopt IPV6_TCLASS (%02x) fails on address %s: %m",
3004b3d6264cSchristos 				qos, stoa(addr));
3005b3d6264cSchristos #endif /* IPPROTO_IPV6 && IPV6_TCLASS */
300645530cf1Skardel #ifdef IPV6_V6ONLY
3007abb0f93cSkardel 		if (isc_net_probe_ipv6only() == ISC_R_SUCCESS
3008abb0f93cSkardel 		    && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
3009169394abSchristos 		    (void *)&on, sizeof(on)))
3010abb0f93cSkardel 			msyslog(LOG_ERR,
3011abb0f93cSkardel 				"setsockopt IPV6_V6ONLY on fails on address %s: %m",
3012abb0f93cSkardel 				stoa(addr));
301345530cf1Skardel #endif
301445530cf1Skardel #ifdef IPV6_BINDV6ONLY
3015abb0f93cSkardel 		if (setsockopt(fd, IPPROTO_IPV6, IPV6_BINDV6ONLY,
3016169394abSchristos 		    (void *)&on, sizeof(on)))
3017abb0f93cSkardel 			msyslog(LOG_ERR,
3018abb0f93cSkardel 				"setsockopt IPV6_BINDV6ONLY on fails on address %s: %m",
3019abb0f93cSkardel 				stoa(addr));
302045530cf1Skardel #endif
3021abb0f93cSkardel 	}
3022abb0f93cSkardel 
3023abb0f93cSkardel #ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND
3024abb0f93cSkardel 	/*
3025abb0f93cSkardel 	 * some OSes don't allow binding to more specific
3026abb0f93cSkardel 	 * addresses if a wildcard address already bound
3027abb0f93cSkardel 	 * to the port and SO_REUSEADDR is not set
3028abb0f93cSkardel 	 */
3029abb0f93cSkardel 	if (!is_wildcard_addr(addr))
3030abb0f93cSkardel 		set_wildcard_reuse(AF(addr), 1);
3031abb0f93cSkardel #endif
3032abb0f93cSkardel 
3033abb0f93cSkardel 	/*
3034abb0f93cSkardel 	 * bind the local address.
3035abb0f93cSkardel 	 */
3036abb0f93cSkardel 	errval = bind(fd, &addr->sa, SOCKLEN(addr));
3037abb0f93cSkardel 
3038abb0f93cSkardel #ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND
3039abb0f93cSkardel 	if (!is_wildcard_addr(addr))
3040abb0f93cSkardel 		set_wildcard_reuse(AF(addr), 0);
3041abb0f93cSkardel #endif
3042abb0f93cSkardel 
3043abb0f93cSkardel 	if (errval < 0) {
3044abb0f93cSkardel 		/*
3045abb0f93cSkardel 		 * Don't log this under all conditions
3046abb0f93cSkardel 		 */
3047abb0f93cSkardel 		if (turn_off_reuse == 0
3048abb0f93cSkardel #ifdef DEBUG
3049abb0f93cSkardel 		    || debug > 1
3050abb0f93cSkardel #endif
3051abb0f93cSkardel 		    ) {
3052abb0f93cSkardel 			msyslog(LOG_ERR,
305324d029faSmlelstv 				"bind(%d) AF_INET%s %s#%d%s flags 0x%x failed: %m",
3054abb0f93cSkardel 				fd, IS_IPV6(addr) ? "6" : "",
305524d029faSmlelstv 				stoa(addr), SRCPORT(addr),
3056abb0f93cSkardel 				IS_MCAST(addr) ? " (multicast)" : "",
3057abb0f93cSkardel 				interf->flags);
3058abb0f93cSkardel 		}
3059abb0f93cSkardel 
3060abb0f93cSkardel 		closesocket(fd);
3061abb0f93cSkardel 
3062abb0f93cSkardel 		return INVALID_SOCKET;
3063abb0f93cSkardel 	}
3064abb0f93cSkardel 
3065abb0f93cSkardel #ifdef HAVE_TIMESTAMP
3066abb0f93cSkardel 	{
3067abb0f93cSkardel 		if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP,
3068169394abSchristos 			       (void *)&on, sizeof(on)))
3069abb0f93cSkardel 			msyslog(LOG_DEBUG,
3070abb0f93cSkardel 				"setsockopt SO_TIMESTAMP on fails on address %s: %m",
3071abb0f93cSkardel 				stoa(addr));
3072abb0f93cSkardel 		else
3073abb0f93cSkardel 			DPRINTF(4, ("setsockopt SO_TIMESTAMP enabled on fd %d address %s\n",
3074abb0f93cSkardel 				    fd, stoa(addr)));
3075abb0f93cSkardel 	}
3076abb0f93cSkardel #endif
3077b3d6264cSchristos #ifdef HAVE_TIMESTAMPNS
3078b3d6264cSchristos 	{
3079b3d6264cSchristos 		if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPNS,
3080169394abSchristos 			       (void *)&on, sizeof(on)))
3081b3d6264cSchristos 			msyslog(LOG_DEBUG,
3082b3d6264cSchristos 				"setsockopt SO_TIMESTAMPNS on fails on address %s: %m",
3083b3d6264cSchristos 				stoa(addr));
3084b3d6264cSchristos 		else
3085b3d6264cSchristos 			DPRINTF(4, ("setsockopt SO_TIMESTAMPNS enabled on fd %d address %s\n",
3086b3d6264cSchristos 				    fd, stoa(addr)));
3087b3d6264cSchristos 	}
3088b3d6264cSchristos #endif
3089b3d6264cSchristos #ifdef HAVE_BINTIME
3090b3d6264cSchristos 	{
3091b3d6264cSchristos 		if (setsockopt(fd, SOL_SOCKET, SO_BINTIME,
3092169394abSchristos 			       (void *)&on, sizeof(on)))
3093b3d6264cSchristos 			msyslog(LOG_DEBUG,
3094b3d6264cSchristos 				"setsockopt SO_BINTIME on fails on address %s: %m",
3095b3d6264cSchristos 				stoa(addr));
3096b3d6264cSchristos 		else
3097b3d6264cSchristos 			DPRINTF(4, ("setsockopt SO_BINTIME enabled on fd %d address %s\n",
3098b3d6264cSchristos 				    fd, stoa(addr)));
3099b3d6264cSchristos 	}
3100b3d6264cSchristos #endif
3101b3d6264cSchristos 
3102abb0f93cSkardel 	DPRINTF(4, ("bind(%d) AF_INET%s, addr %s%%%d#%d, flags 0x%x\n",
3103abb0f93cSkardel 		   fd, IS_IPV6(addr) ? "6" : "", stoa(addr),
3104abb0f93cSkardel 		   SCOPE(addr), SRCPORT(addr), interf->flags));
3105abb0f93cSkardel 
3106b3d6264cSchristos 	make_socket_nonblocking(fd);
3107abb0f93cSkardel 
3108abb0f93cSkardel #ifdef HAVE_SIGNALED_IO
3109abb0f93cSkardel 	init_socket_sig(fd);
3110abb0f93cSkardel #endif /* not HAVE_SIGNALED_IO */
3111abb0f93cSkardel 
3112abb0f93cSkardel 	add_fd_to_list(fd, FD_TYPE_SOCKET);
3113abb0f93cSkardel 
3114abb0f93cSkardel #if !defined(SYS_WINNT) && !defined(VMS)
3115abb0f93cSkardel 	DPRINTF(4, ("flags for fd %d: 0x%x\n", fd,
3116abb0f93cSkardel 		    fcntl(fd, F_GETFL, 0)));
3117abb0f93cSkardel #endif /* SYS_WINNT || VMS */
3118abb0f93cSkardel 
3119abb0f93cSkardel #if defined(HAVE_IO_COMPLETION_PORT)
3120abb0f93cSkardel /*
3121abb0f93cSkardel  * Add the socket to the completion port
3122abb0f93cSkardel  */
3123335f7552Schristos 	if (!io_completion_port_add_socket(fd, interf, bcast)) {
3124abb0f93cSkardel 		msyslog(LOG_ERR, "unable to set up io completion port - EXITING");
3125abb0f93cSkardel 		exit(1);
3126abb0f93cSkardel 	}
3127abb0f93cSkardel #endif
3128abb0f93cSkardel 	return fd;
3129abb0f93cSkardel }
3130abb0f93cSkardel 
313145530cf1Skardel 
313245530cf1Skardel 
3133abb0f93cSkardel /* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
3134abb0f93cSkardel /*
3135abb0f93cSkardel  * sendpkt - send a packet to the specified destination. Maintain a
3136abb0f93cSkardel  * send error cache so that only the first consecutive error for a
3137abb0f93cSkardel  * destination is logged.
3138abb0f93cSkardel  */
3139abb0f93cSkardel void
3140abb0f93cSkardel sendpkt(
3141abb0f93cSkardel 	sockaddr_u *		dest,
314245530cf1Skardel 	struct interface *	ep,
3143abb0f93cSkardel 	int			ttl,
3144abb0f93cSkardel 	struct pkt *		pkt,
3145abb0f93cSkardel 	int			len
3146abb0f93cSkardel 	)
3147abb0f93cSkardel {
314845530cf1Skardel 	endpt *	src;
314945530cf1Skardel 	int	ismcast;
3150abb0f93cSkardel 	int	cc;
315145530cf1Skardel 	int	rc;
315245530cf1Skardel 	u_char	cttl;
31539034ec65Schristos 	l_fp	fp_zero = { { 0 }, 0 };
31549034ec65Schristos 	l_fp	org, rec, xmt;
3155abb0f93cSkardel 
315645530cf1Skardel 	ismcast = IS_MCAST(dest);
315745530cf1Skardel 	if (!ismcast)
315845530cf1Skardel 		src = ep;
315945530cf1Skardel 	else
316045530cf1Skardel 		src = (IS_IPV4(dest))
316145530cf1Skardel 			  ? mc4_list
316245530cf1Skardel 			  : mc6_list;
316345530cf1Skardel 
316445530cf1Skardel 	if (NULL == src) {
3165abb0f93cSkardel 		/*
3166abb0f93cSkardel 		 * unbound peer - drop request and wait for better
3167abb0f93cSkardel 		 * network conditions
3168abb0f93cSkardel 		 */
3169abb0f93cSkardel 		DPRINTF(2, ("%ssendpkt(dst=%s, ttl=%d, len=%d): no interface - IGNORED\n",
317045530cf1Skardel 			    ismcast ? "\tMCAST\t***** " : "",
3171abb0f93cSkardel 			    stoa(dest), ttl, len));
3172abb0f93cSkardel 		return;
3173abb0f93cSkardel 	}
3174abb0f93cSkardel 
317545530cf1Skardel 	do {
3176abb0f93cSkardel 		DPRINTF(2, ("%ssendpkt(%d, dst=%s, src=%s, ttl=%d, len=%d)\n",
317745530cf1Skardel 			    ismcast ? "\tMCAST\t***** " : "", src->fd,
317845530cf1Skardel 			    stoa(dest), stoa(&src->sin), ttl, len));
3179abb0f93cSkardel #ifdef MCAST
3180abb0f93cSkardel 		/*
3181abb0f93cSkardel 		 * for the moment we use the bcast option to set multicast ttl
3182abb0f93cSkardel 		 */
318345530cf1Skardel 		if (ismcast && ttl > 0 && ttl != src->last_ttl) {
3184abb0f93cSkardel 			/*
3185abb0f93cSkardel 			 * set the multicast ttl for outgoing packets
3186abb0f93cSkardel 			 */
318745530cf1Skardel 			switch (AF(&src->sin)) {
3188abb0f93cSkardel 
3189abb0f93cSkardel 			case AF_INET :
3190abb0f93cSkardel 				cttl = (u_char)ttl;
319145530cf1Skardel 				rc = setsockopt(src->fd, IPPROTO_IP,
3192abb0f93cSkardel 						IP_MULTICAST_TTL,
319345530cf1Skardel 						(void *)&cttl,
319445530cf1Skardel 						sizeof(cttl));
3195abb0f93cSkardel 				break;
3196abb0f93cSkardel 
3197abb0f93cSkardel # ifdef INCLUDE_IPV6_SUPPORT
3198abb0f93cSkardel 			case AF_INET6 :
319945530cf1Skardel 				rc = setsockopt(src->fd, IPPROTO_IPV6,
3200abb0f93cSkardel 						 IPV6_MULTICAST_HOPS,
320145530cf1Skardel 						 (void *)&ttl,
320245530cf1Skardel 						 sizeof(ttl));
3203abb0f93cSkardel 				break;
3204abb0f93cSkardel # endif	/* INCLUDE_IPV6_SUPPORT */
3205abb0f93cSkardel 
320645530cf1Skardel 			default:
320745530cf1Skardel 				rc = 0;
3208abb0f93cSkardel 			}
3209abb0f93cSkardel 
321045530cf1Skardel 			if (!rc)
321145530cf1Skardel 				src->last_ttl = ttl;
3212abb0f93cSkardel 			else
3213abb0f93cSkardel 				msyslog(LOG_ERR,
3214abb0f93cSkardel 					"setsockopt IP_MULTICAST_TTL/IPV6_MULTICAST_HOPS fails on address %s: %m",
321545530cf1Skardel 					stoa(&src->sin));
3216abb0f93cSkardel 		}
3217abb0f93cSkardel #endif	/* MCAST */
3218abb0f93cSkardel 
3219abb0f93cSkardel #ifdef SIM
322045530cf1Skardel 		cc = simulate_server(dest, src, pkt);
3221335f7552Schristos #elif defined(HAVE_IO_COMPLETION_PORT)
3222335f7552Schristos 		cc = io_completion_port_sendto(src, src->fd, pkt,
3223335f7552Schristos 			(size_t)len, (sockaddr_u *)&dest->sa);
322445530cf1Skardel #else
322545530cf1Skardel 		cc = sendto(src->fd, (char *)pkt, (u_int)len, 0,
322645530cf1Skardel 			    &dest->sa, SOCKLEN(dest));
3227abb0f93cSkardel #endif
322845530cf1Skardel 		if (cc == -1) {
322945530cf1Skardel 			src->notsent++;
3230abb0f93cSkardel 			packets_notsent++;
3231abb0f93cSkardel 		} else	{
323245530cf1Skardel 			src->sent++;
3233abb0f93cSkardel 			packets_sent++;
3234abb0f93cSkardel 		}
323545530cf1Skardel 		if (ismcast)
323645530cf1Skardel 			src = src->mclink;
323745530cf1Skardel 	} while (ismcast && src != NULL);
3238169394abSchristos 
3239169394abSchristos 	/* HMS: pkt->rootdisp is usually random here */
32409034ec65Schristos 	NTOHL_FP(&pkt->org, &org);
32419034ec65Schristos 	NTOHL_FP(&pkt->rec, &rec);
32429034ec65Schristos 	NTOHL_FP(&pkt->xmt, &xmt);
3243169394abSchristos 	record_raw_stats(src ? &src->sin : NULL, dest,
32449034ec65Schristos 			&org, &rec, &xmt, &fp_zero,
3245169394abSchristos 			PKT_LEAP(pkt->li_vn_mode),
32469034ec65Schristos 			PKT_VERSION(pkt->li_vn_mode),
32479034ec65Schristos 			PKT_MODE(pkt->li_vn_mode),
3248169394abSchristos 			pkt->stratum,
3249169394abSchristos 			pkt->ppoll, pkt->precision,
3250169394abSchristos 			pkt->rootdelay, pkt->rootdisp, pkt->refid,
3251169394abSchristos 			len - MIN_V4_PKT_LEN, (u_char *)&pkt->exten);
3252169394abSchristos 
3253169394abSchristos 	return;
3254abb0f93cSkardel }
3255abb0f93cSkardel 
3256abb0f93cSkardel 
3257abb0f93cSkardel #if !defined(HAVE_IO_COMPLETION_PORT)
3258335f7552Schristos #if !defined(HAVE_SIGNALED_IO)
3259abb0f93cSkardel /*
3260abb0f93cSkardel  * fdbits - generate ascii representation of fd_set (FAU debug support)
3261abb0f93cSkardel  * HFDF format - highest fd first.
3262abb0f93cSkardel  */
3263abb0f93cSkardel static char *
3264abb0f93cSkardel fdbits(
3265abb0f93cSkardel 	int		count,
3266335f7552Schristos 	const fd_set*	set
3267abb0f93cSkardel 	)
3268abb0f93cSkardel {
3269abb0f93cSkardel 	static char buffer[256];
3270abb0f93cSkardel 	char * buf = buffer;
3271abb0f93cSkardel 
3272abb0f93cSkardel 	count = min(count,  255);
3273abb0f93cSkardel 
3274abb0f93cSkardel 	while (count >= 0) {
3275abb0f93cSkardel 		*buf++ = FD_ISSET(count, set) ? '#' : '-';
3276abb0f93cSkardel 		count--;
3277abb0f93cSkardel 	}
3278abb0f93cSkardel 	*buf = '\0';
3279abb0f93cSkardel 
3280abb0f93cSkardel 	return buffer;
3281abb0f93cSkardel }
3282335f7552Schristos #endif
3283b3d6264cSchristos 
3284b3d6264cSchristos #ifdef REFCLOCK
3285abb0f93cSkardel /*
3286abb0f93cSkardel  * Routine to read the refclock packets for a specific interface
3287abb0f93cSkardel  * Return the number of bytes read. That way we know if we should
3288abb0f93cSkardel  * read it again or go on to the next one if no bytes returned
3289abb0f93cSkardel  */
3290abb0f93cSkardel static inline int
3291b3d6264cSchristos read_refclock_packet(
3292b3d6264cSchristos 	SOCKET			fd,
3293b3d6264cSchristos 	struct refclockio *	rp,
3294b3d6264cSchristos 	l_fp			ts
3295b3d6264cSchristos 	)
3296abb0f93cSkardel {
329709f14f80Schristos 	u_int			read_count;
3298abb0f93cSkardel 	int			buflen;
3299b3d6264cSchristos 	int			saved_errno;
3300b3d6264cSchristos 	int			consumed;
3301b3d6264cSchristos 	struct recvbuf *	rb;
3302abb0f93cSkardel 
3303*e03b00c8Schristos 	rb = get_free_recv_buffer(TRUE);
3304abb0f93cSkardel 
3305abb0f93cSkardel 	if (NULL == rb) {
3306abb0f93cSkardel 		/*
3307*e03b00c8Schristos 		 * No buffer space available - just drop the 'packet'.
3308*e03b00c8Schristos 		 * Since this is a non-blocking character stream we read
3309*e03b00c8Schristos 		 * all data that we can.
3310*e03b00c8Schristos 		 *
3311*e03b00c8Schristos 		 * ...hmmmm... what about "tcflush(fd,TCIFLUSH)" here?!?
3312abb0f93cSkardel 		 */
3313*e03b00c8Schristos 		char buf[128];
3314*e03b00c8Schristos 		do
3315*e03b00c8Schristos 			buflen = read(fd, buf, sizeof(buf));
3316*e03b00c8Schristos 		while (buflen > 0);
3317abb0f93cSkardel 		packets_dropped++;
3318abb0f93cSkardel 		return (buflen);
3319abb0f93cSkardel 	}
3320abb0f93cSkardel 
332109f14f80Schristos 	/* TALOS-CAN-0064: avoid signed/unsigned clashes that can lead
332209f14f80Schristos 	 * to buffer overrun and memory corruption
332309f14f80Schristos 	 */
332409f14f80Schristos 	if (rp->datalen <= 0 || (size_t)rp->datalen > sizeof(rb->recv_space))
332509f14f80Schristos 		read_count = sizeof(rb->recv_space);
332609f14f80Schristos 	else
332709f14f80Schristos 		read_count = (u_int)rp->datalen;
3328b3d6264cSchristos 	do {
332909f14f80Schristos 		buflen = read(fd, (char *)&rb->recv_space, read_count);
3330b3d6264cSchristos 	} while (buflen < 0 && EINTR == errno);
3331abb0f93cSkardel 
3332b3d6264cSchristos 	if (buflen <= 0) {
3333b3d6264cSchristos 		saved_errno = errno;
3334abb0f93cSkardel 		freerecvbuf(rb);
3335b3d6264cSchristos 		errno = saved_errno;
3336b3d6264cSchristos 		return buflen;
3337abb0f93cSkardel 	}
3338abb0f93cSkardel 
3339abb0f93cSkardel 	/*
3340abb0f93cSkardel 	 * Got one. Mark how and when it got here,
3341abb0f93cSkardel 	 * put it on the full list and do bookkeeping.
3342abb0f93cSkardel 	 */
3343abb0f93cSkardel 	rb->recv_length = buflen;
3344b3d6264cSchristos 	rb->recv_peer = rp->srcclock;
3345abb0f93cSkardel 	rb->dstadr = 0;
3346abb0f93cSkardel 	rb->fd = fd;
3347abb0f93cSkardel 	rb->recv_time = ts;
3348abb0f93cSkardel 	rb->receiver = rp->clock_recv;
3349abb0f93cSkardel 
3350b3d6264cSchristos 	consumed = indicate_refclock_packet(rp, rb);
3351b3d6264cSchristos 	if (!consumed) {
3352abb0f93cSkardel 		rp->recvcount++;
3353abb0f93cSkardel 		packets_received++;
3354abb0f93cSkardel 	}
3355abb0f93cSkardel 
3356b3d6264cSchristos 	return buflen;
3357b3d6264cSchristos }
3358b3d6264cSchristos #endif	/* REFCLOCK */
3359abb0f93cSkardel 
3360b3d6264cSchristos 
3361b3d6264cSchristos #ifdef HAVE_PACKET_TIMESTAMP
3362abb0f93cSkardel /*
3363abb0f93cSkardel  * extract timestamps from control message buffer
3364abb0f93cSkardel  */
3365abb0f93cSkardel static l_fp
3366abb0f93cSkardel fetch_timestamp(
3367abb0f93cSkardel 	struct recvbuf *	rb,
3368abb0f93cSkardel 	struct msghdr *		msghdr,
3369abb0f93cSkardel 	l_fp			ts
3370abb0f93cSkardel 	)
3371abb0f93cSkardel {
3372abb0f93cSkardel 	struct cmsghdr *	cmsghdr;
3373b3d6264cSchristos 	unsigned long		ticks;
3374b3d6264cSchristos 	double			fuzz;
3375b3d6264cSchristos 	l_fp			lfpfuzz;
3376b3d6264cSchristos 	l_fp			nts;
3377b3d6264cSchristos #ifdef DEBUG_TIMING
3378b3d6264cSchristos 	l_fp			dts;
3379b3d6264cSchristos #endif
3380abb0f93cSkardel 
3381abb0f93cSkardel 	cmsghdr = CMSG_FIRSTHDR(msghdr);
3382abb0f93cSkardel 	while (cmsghdr != NULL) {
3383abb0f93cSkardel 		switch (cmsghdr->cmsg_type)
3384abb0f93cSkardel 		{
3385b3d6264cSchristos #ifdef HAVE_BINTIME
3386b3d6264cSchristos 		case SCM_BINTIME:
3387b3d6264cSchristos #endif  /* HAVE_BINTIME */
3388b3d6264cSchristos #ifdef HAVE_TIMESTAMPNS
3389b3d6264cSchristos 		case SCM_TIMESTAMPNS:
3390b3d6264cSchristos #endif	/* HAVE_TIMESTAMPNS */
3391b3d6264cSchristos #ifdef HAVE_TIMESTAMP
3392abb0f93cSkardel 		case SCM_TIMESTAMP:
3393b3d6264cSchristos #endif	/* HAVE_TIMESTAMP */
3394b3d6264cSchristos #if defined(HAVE_BINTIME) || defined (HAVE_TIMESTAMPNS) || defined(HAVE_TIMESTAMP)
3395b3d6264cSchristos 			switch (cmsghdr->cmsg_type)
3396abb0f93cSkardel 			{
3397b3d6264cSchristos #ifdef HAVE_BINTIME
3398b3d6264cSchristos 			case SCM_BINTIME:
339966fcc386Schristos 				{
340066fcc386Schristos 					struct bintime	pbt;
340166fcc386Schristos 					memcpy(&pbt, CMSG_DATA(cmsghdr), sizeof(pbt));
3402b3d6264cSchristos 					/*
3403b3d6264cSchristos 					 * bintime documentation is at http://phk.freebsd.dk/pubs/timecounter.pdf
3404b3d6264cSchristos 					 */
340566fcc386Schristos 					nts.l_i = pbt.sec + JAN_1970;
340666fcc386Schristos 					nts.l_uf = (u_int32)(pbt.frac >> 32);
3407b3d6264cSchristos 					if (sys_tick > measured_tick &&
3408b3d6264cSchristos 					    sys_tick > 1e-9) {
3409b3d6264cSchristos 						ticks = (unsigned long)(nts.l_uf / (unsigned long)(sys_tick * FRAC));
3410b3d6264cSchristos 						nts.l_uf = (unsigned long)(ticks * (unsigned long)(sys_tick * FRAC));
3411b3d6264cSchristos 					}
3412b3d6264cSchristos 					DPRINTF(4, ("fetch_timestamp: system bintime network time stamp: %ld.%09lu\n",
341366fcc386Schristos 						    pbt.sec, (unsigned long)((nts.l_uf / FRAC) * 1e9)));
341466fcc386Schristos 				}
3415b3d6264cSchristos 				break;
3416b3d6264cSchristos #endif  /* HAVE_BINTIME */
3417b3d6264cSchristos #ifdef HAVE_TIMESTAMPNS
3418b3d6264cSchristos 			case SCM_TIMESTAMPNS:
341966fcc386Schristos 				{
342066fcc386Schristos 					struct timespec	pts;
342166fcc386Schristos 					memcpy(&pts, CMSG_DATA(cmsghdr), sizeof(pts));
3422b3d6264cSchristos 					if (sys_tick > measured_tick &&
3423b3d6264cSchristos 					    sys_tick > 1e-9) {
342466fcc386Schristos 						ticks = (unsigned long)((pts.tv_nsec * 1e-9) /
3425b3d6264cSchristos 									sys_tick);
342666fcc386Schristos 						pts.tv_nsec = (long)(ticks * 1e9 *
3427b3d6264cSchristos 								     sys_tick);
3428b3d6264cSchristos 					}
3429b3d6264cSchristos 					DPRINTF(4, ("fetch_timestamp: system nsec network time stamp: %ld.%09ld\n",
343066fcc386Schristos 						    pts.tv_sec, pts.tv_nsec));
343166fcc386Schristos 					nts = tspec_stamp_to_lfp(pts);
343266fcc386Schristos 				}
3433b3d6264cSchristos 				break;
3434b3d6264cSchristos #endif	/* HAVE_TIMESTAMPNS */
3435b3d6264cSchristos #ifdef HAVE_TIMESTAMP
3436b3d6264cSchristos 			case SCM_TIMESTAMP:
343766fcc386Schristos 				{
343866fcc386Schristos 					struct timeval	ptv;
343966fcc386Schristos 					memcpy(&ptv, CMSG_DATA(cmsghdr), sizeof(ptv));
3440b3d6264cSchristos 					if (sys_tick > measured_tick &&
3441b3d6264cSchristos 					    sys_tick > 1e-6) {
344266fcc386Schristos 						ticks = (unsigned long)((ptv.tv_usec * 1e-6) /
3443b3d6264cSchristos 									sys_tick);
344466fcc386Schristos 						ptv.tv_usec = (long)(ticks * 1e6 *
3445b3d6264cSchristos 								    sys_tick);
3446b3d6264cSchristos 					}
344774fd00ffSchristos 					DPRINTF(4, ("fetch_timestamp: system usec network time stamp: %jd.%06ld\n",
344866fcc386Schristos 						    (intmax_t)ptv.tv_sec, (long)ptv.tv_usec));
344966fcc386Schristos 					nts = tval_stamp_to_lfp(ptv);
345066fcc386Schristos 				}
3451b3d6264cSchristos 				break;
3452b3d6264cSchristos #endif  /* HAVE_TIMESTAMP */
3453b3d6264cSchristos 			}
3454b3d6264cSchristos 			fuzz = ntp_random() * 2. / FRAC * sys_fuzz;
3455b3d6264cSchristos 			DTOLFP(fuzz, &lfpfuzz);
3456b3d6264cSchristos 			L_ADD(&nts, &lfpfuzz);
3457abb0f93cSkardel #ifdef DEBUG_TIMING
3458abb0f93cSkardel 			dts = ts;
3459abb0f93cSkardel 			L_SUB(&dts, &nts);
3460b3d6264cSchristos 			collect_timing(rb, "input processing delay", 1,
3461b3d6264cSchristos 				       &dts);
3462b3d6264cSchristos 			DPRINTF(4, ("fetch_timestamp: timestamp delta: %s (incl. fuzz)\n",
3463abb0f93cSkardel 				    lfptoa(&dts, 9)));
3464b3d6264cSchristos #endif	/* DEBUG_TIMING */
3465abb0f93cSkardel 			ts = nts;  /* network time stamp */
3466abb0f93cSkardel 			break;
3467b3d6264cSchristos #endif	/* HAVE_BINTIME || HAVE_TIMESTAMPNS || HAVE_TIMESTAMP */
3468b3d6264cSchristos 
3469abb0f93cSkardel 		default:
3470abb0f93cSkardel 			DPRINTF(4, ("fetch_timestamp: skipping control message 0x%x\n",
3471abb0f93cSkardel 				    cmsghdr->cmsg_type));
3472abb0f93cSkardel 		}
3473abb0f93cSkardel 		cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr);
3474abb0f93cSkardel 	}
3475abb0f93cSkardel 	return ts;
3476abb0f93cSkardel }
3477b3d6264cSchristos #endif	/* HAVE_PACKET_TIMESTAMP */
3478abb0f93cSkardel 
3479abb0f93cSkardel 
3480abb0f93cSkardel /*
3481abb0f93cSkardel  * Routine to read the network NTP packets for a specific interface
3482abb0f93cSkardel  * Return the number of bytes read. That way we know if we should
3483abb0f93cSkardel  * read it again or go on to the next one if no bytes returned
3484abb0f93cSkardel  */
3485abb0f93cSkardel static inline int
3486abb0f93cSkardel read_network_packet(
3487abb0f93cSkardel 	SOCKET			fd,
3488abb0f93cSkardel 	struct interface *	itf,
3489abb0f93cSkardel 	l_fp			ts
3490abb0f93cSkardel 	)
3491abb0f93cSkardel {
3492abb0f93cSkardel 	GETSOCKNAME_SOCKLEN_TYPE fromlen;
3493abb0f93cSkardel 	int buflen;
3494abb0f93cSkardel 	register struct recvbuf *rb;
3495b3d6264cSchristos #ifdef HAVE_PACKET_TIMESTAMP
3496abb0f93cSkardel 	struct msghdr msghdr;
3497abb0f93cSkardel 	struct iovec iovec;
3498b3d6264cSchristos 	char control[CMSG_BUFSIZE];
3499abb0f93cSkardel #endif
3500abb0f93cSkardel 
3501abb0f93cSkardel 	/*
3502*e03b00c8Schristos 	 * Get a buffer and read the frame.  If we haven't got a buffer,
3503*e03b00c8Schristos 	 * or this is received on a disallowed socket, just dump the
3504abb0f93cSkardel 	 * packet.
3505abb0f93cSkardel 	 */
3506abb0f93cSkardel 
3507*e03b00c8Schristos 	rb = itf->ignore_packets ? NULL : get_free_recv_buffer(FALSE);
3508*e03b00c8Schristos 	if (NULL == rb) {
3509*e03b00c8Schristos 		/* A partial read on a UDP socket truncates the data and
3510*e03b00c8Schristos 		 * removes the message from the queue. So there's no
3511*e03b00c8Schristos 		 * need to have a full buffer here on the stack.
3512*e03b00c8Schristos 		 */
3513*e03b00c8Schristos 		char buf[16];
3514abb0f93cSkardel 		sockaddr_u from;
3515abb0f93cSkardel 
3516abb0f93cSkardel 		if (rb != NULL)
3517abb0f93cSkardel 			freerecvbuf(rb);
3518abb0f93cSkardel 
3519abb0f93cSkardel 		fromlen = sizeof(from);
3520abb0f93cSkardel 		buflen = recvfrom(fd, buf, sizeof(buf), 0,
3521abb0f93cSkardel 				  &from.sa, &fromlen);
3522abb0f93cSkardel 		DPRINTF(4, ("%s on (%lu) fd=%d from %s\n",
3523abb0f93cSkardel 			(itf->ignore_packets)
3524abb0f93cSkardel 			    ? "ignore"
3525abb0f93cSkardel 			    : "drop",
3526abb0f93cSkardel 			free_recvbuffs(), fd, stoa(&from)));
3527abb0f93cSkardel 		if (itf->ignore_packets)
3528abb0f93cSkardel 			packets_ignored++;
3529abb0f93cSkardel 		else
3530abb0f93cSkardel 			packets_dropped++;
3531abb0f93cSkardel 		return (buflen);
3532abb0f93cSkardel 	}
3533abb0f93cSkardel 
3534abb0f93cSkardel 	fromlen = sizeof(rb->recv_srcadr);
3535abb0f93cSkardel 
3536b3d6264cSchristos #ifndef HAVE_PACKET_TIMESTAMP
3537abb0f93cSkardel 	rb->recv_length = recvfrom(fd, (char *)&rb->recv_space,
3538abb0f93cSkardel 				   sizeof(rb->recv_space), 0,
3539abb0f93cSkardel 				   &rb->recv_srcadr.sa, &fromlen);
3540abb0f93cSkardel #else
3541abb0f93cSkardel 	iovec.iov_base        = &rb->recv_space;
3542abb0f93cSkardel 	iovec.iov_len         = sizeof(rb->recv_space);
3543abb0f93cSkardel 	msghdr.msg_name       = &rb->recv_srcadr;
3544abb0f93cSkardel 	msghdr.msg_namelen    = fromlen;
3545abb0f93cSkardel 	msghdr.msg_iov        = &iovec;
3546abb0f93cSkardel 	msghdr.msg_iovlen     = 1;
3547abb0f93cSkardel 	msghdr.msg_control    = (void *)&control;
3548abb0f93cSkardel 	msghdr.msg_controllen = sizeof(control);
3549abb0f93cSkardel 	msghdr.msg_flags      = 0;
3550abb0f93cSkardel 	rb->recv_length       = recvmsg(fd, &msghdr, 0);
3551abb0f93cSkardel #endif
3552abb0f93cSkardel 
3553abb0f93cSkardel 	buflen = rb->recv_length;
3554abb0f93cSkardel 
3555abb0f93cSkardel 	if (buflen == 0 || (buflen == -1 &&
3556abb0f93cSkardel 	    (EWOULDBLOCK == errno
3557abb0f93cSkardel #ifdef EAGAIN
3558abb0f93cSkardel 	     || EAGAIN == errno
3559abb0f93cSkardel #endif
3560abb0f93cSkardel 	     ))) {
3561abb0f93cSkardel 		freerecvbuf(rb);
3562abb0f93cSkardel 		return (buflen);
3563abb0f93cSkardel 	} else if (buflen < 0) {
3564abb0f93cSkardel 		msyslog(LOG_ERR, "recvfrom(%s) fd=%d: %m",
3565abb0f93cSkardel 			stoa(&rb->recv_srcadr), fd);
3566abb0f93cSkardel 		DPRINTF(5, ("read_network_packet: fd=%d dropped (bad recvfrom)\n",
3567abb0f93cSkardel 			    fd));
3568abb0f93cSkardel 		freerecvbuf(rb);
3569abb0f93cSkardel 		return (buflen);
3570abb0f93cSkardel 	}
3571abb0f93cSkardel 
3572abb0f93cSkardel 	DPRINTF(3, ("read_network_packet: fd=%d length %d from %s\n",
3573abb0f93cSkardel 		    fd, buflen, stoa(&rb->recv_srcadr)));
3574abb0f93cSkardel 
3575335f7552Schristos #ifdef ENABLE_BUG3020_FIX
3576335f7552Schristos 	if (ISREFCLOCKADR(&rb->recv_srcadr)) {
3577335f7552Schristos 		msyslog(LOG_ERR, "recvfrom(%s) fd=%d: refclock srcadr on a network interface!",
3578335f7552Schristos 			stoa(&rb->recv_srcadr), fd);
3579335f7552Schristos 		DPRINTF(1, ("read_network_packet: fd=%d dropped (refclock srcadr))\n",
3580335f7552Schristos 			    fd));
3581335f7552Schristos 		packets_dropped++;
3582335f7552Schristos 		freerecvbuf(rb);
3583335f7552Schristos 		return (buflen);
3584335f7552Schristos 	}
3585335f7552Schristos #endif
3586335f7552Schristos 
3587abb0f93cSkardel 	/*
3588ad131110Schristos 	** Bug 2672: Some OSes (MacOSX and Linux) don't block spoofed ::1
3589ad131110Schristos 	*/
3590ad131110Schristos 
3591ad131110Schristos 	if (AF_INET6 == itf->family) {
359250cc4415Schristos 		DPRINTF(2, ("Got an IPv6 packet, from <%s> (%d) to <%s> (%d)\n",
3593ad131110Schristos 			stoa(&rb->recv_srcadr),
359450cc4415Schristos 			IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&rb->recv_srcadr)),
3595ad131110Schristos 			stoa(&itf->sin),
359650cc4415Schristos 			!IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&itf->sin))
3597ad131110Schristos 			));
3598ad131110Schristos 
359950cc4415Schristos 		if (   IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&rb->recv_srcadr))
360050cc4415Schristos 		    && !IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&itf->sin))
3601ad131110Schristos 		   ) {
3602ad131110Schristos 			packets_dropped++;
360350cc4415Schristos 			DPRINTF(2, ("DROPPING that packet\n"));
3604ad131110Schristos 			freerecvbuf(rb);
3605ad131110Schristos 			return buflen;
3606ad131110Schristos 		}
360750cc4415Schristos 		DPRINTF(2, ("processing that packet\n"));
360850cc4415Schristos 	}
3609ad131110Schristos 
3610ad131110Schristos 	/*
3611abb0f93cSkardel 	 * Got one.  Mark how and when it got here,
3612abb0f93cSkardel 	 * put it on the full list and do bookkeeping.
3613abb0f93cSkardel 	 */
3614abb0f93cSkardel 	rb->dstadr = itf;
3615abb0f93cSkardel 	rb->fd = fd;
3616b3d6264cSchristos #ifdef HAVE_PACKET_TIMESTAMP
3617abb0f93cSkardel 	/* pick up a network time stamp if possible */
3618abb0f93cSkardel 	ts = fetch_timestamp(rb, &msghdr, ts);
3619abb0f93cSkardel #endif
3620abb0f93cSkardel 	rb->recv_time = ts;
3621abb0f93cSkardel 	rb->receiver = receive;
3622abb0f93cSkardel 
3623abb0f93cSkardel 	add_full_recv_buffer(rb);
3624abb0f93cSkardel 
3625abb0f93cSkardel 	itf->received++;
3626abb0f93cSkardel 	packets_received++;
3627abb0f93cSkardel 	return (buflen);
3628abb0f93cSkardel }
3629abb0f93cSkardel 
3630b3d6264cSchristos /*
3631b3d6264cSchristos  * attempt to handle io (select()/signaled IO)
3632b3d6264cSchristos  */
3633b3d6264cSchristos void
3634b3d6264cSchristos io_handler(void)
3635b3d6264cSchristos {
3636b3d6264cSchristos #  ifndef HAVE_SIGNALED_IO
3637b3d6264cSchristos 	fd_set rdfdes;
3638b3d6264cSchristos 	int nfound;
3639b3d6264cSchristos 
3640b3d6264cSchristos 	/*
3641b3d6264cSchristos 	 * Use select() on all on all input fd's for unlimited
3642b3d6264cSchristos 	 * time.  select() will terminate on SIGALARM or on the
3643b3d6264cSchristos 	 * reception of input.	Using select() means we can't do
3644b3d6264cSchristos 	 * robust signal handling and we get a potential race
3645b3d6264cSchristos 	 * between checking for alarms and doing the select().
3646b3d6264cSchristos 	 * Mostly harmless, I think.
3647b3d6264cSchristos 	 */
3648b3d6264cSchristos 	/*
3649b3d6264cSchristos 	 * On VMS, I suspect that select() can't be interrupted
3650b3d6264cSchristos 	 * by a "signal" either, so I take the easy way out and
3651b3d6264cSchristos 	 * have select() time out after one second.
3652b3d6264cSchristos 	 * System clock updates really aren't time-critical,
3653b3d6264cSchristos 	 * and - lacking a hardware reference clock - I have
3654b3d6264cSchristos 	 * yet to learn about anything else that is.
3655b3d6264cSchristos 	 */
3656335f7552Schristos 	++handler_calls;
3657b3d6264cSchristos 	rdfdes = activefds;
3658b3d6264cSchristos #   if !defined(VMS) && !defined(SYS_VXWORKS)
3659b3d6264cSchristos 	nfound = select(maxactivefd + 1, &rdfdes, NULL,
3660b3d6264cSchristos 			NULL, NULL);
3661b3d6264cSchristos #   else	/* VMS, VxWorks */
3662b3d6264cSchristos 	/* make select() wake up after one second */
3663b3d6264cSchristos 	{
3664b3d6264cSchristos 		struct timeval t1;
3665b3d6264cSchristos 		t1.tv_sec  = 1;
3666b3d6264cSchristos 		t1.tv_usec = 0;
3667b3d6264cSchristos 		nfound = select(maxactivefd + 1,
3668b3d6264cSchristos 				&rdfdes, NULL, NULL,
3669b3d6264cSchristos 				&t1);
3670b3d6264cSchristos 	}
3671b3d6264cSchristos #   endif	/* VMS, VxWorks */
3672335f7552Schristos 	if (nfound < 0 && sanitize_fdset(errno)) {
3673335f7552Schristos 		struct timeval t1;
3674335f7552Schristos 		t1.tv_sec  = 0;
3675335f7552Schristos 		t1.tv_usec = 0;
3676335f7552Schristos 		rdfdes = activefds;
3677335f7552Schristos 		nfound = select(maxactivefd + 1,
3678335f7552Schristos 				&rdfdes, NULL, NULL,
3679335f7552Schristos 				&t1);
3680335f7552Schristos 	}
3681335f7552Schristos 
3682b3d6264cSchristos 	if (nfound > 0) {
3683b3d6264cSchristos 		l_fp ts;
3684b3d6264cSchristos 
3685b3d6264cSchristos 		get_systime(&ts);
3686b3d6264cSchristos 
3687335f7552Schristos 		input_handler_scan(&ts, &rdfdes);
3688b3d6264cSchristos 	} else if (nfound == -1 && errno != EINTR) {
3689b3d6264cSchristos 		msyslog(LOG_ERR, "select() error: %m");
3690b3d6264cSchristos 	}
3691b3d6264cSchristos #   ifdef DEBUG
3692b3d6264cSchristos 	else if (debug > 4) {
3693b3d6264cSchristos 		msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
3694b3d6264cSchristos 	} else {
36954e3b3909Schristos 		DPRINTF(3, ("select() returned %d: %m\n", nfound));
3696b3d6264cSchristos 	}
3697b3d6264cSchristos #   endif /* DEBUG */
3698b3d6264cSchristos #  else /* HAVE_SIGNALED_IO */
3699b3d6264cSchristos 	wait_for_signal();
3700b3d6264cSchristos #  endif /* HAVE_SIGNALED_IO */
3701b3d6264cSchristos }
3702abb0f93cSkardel 
3703335f7552Schristos #ifdef HAVE_SIGNALED_IO
3704abb0f93cSkardel /*
3705abb0f93cSkardel  * input_handler - receive packets asynchronously
3706335f7552Schristos  *
3707335f7552Schristos  * ALWAYS IN SIGNAL HANDLER CONTEXT -- only async-safe functions allowed!
3708abb0f93cSkardel  */
3709335f7552Schristos static RETSIGTYPE
3710abb0f93cSkardel input_handler(
3711abb0f93cSkardel 	l_fp *	cts
3712abb0f93cSkardel 	)
3713abb0f93cSkardel {
3714abb0f93cSkardel 	int		n;
3715335f7552Schristos 	struct timeval	tvzero;
3716335f7552Schristos 	fd_set		fds;
3717335f7552Schristos 
3718335f7552Schristos 	++handler_calls;
3719335f7552Schristos 
3720335f7552Schristos 	/*
3721335f7552Schristos 	 * Do a poll to see who has data
3722335f7552Schristos 	 */
3723335f7552Schristos 
3724335f7552Schristos 	fds = activefds;
3725335f7552Schristos 	tvzero.tv_sec = tvzero.tv_usec = 0;
3726335f7552Schristos 
3727335f7552Schristos 	n = select(maxactivefd + 1, &fds, NULL, NULL, &tvzero);
3728335f7552Schristos 	if (n < 0 && sanitize_fdset(errno)) {
3729335f7552Schristos 		fds = activefds;
3730335f7552Schristos 		tvzero.tv_sec = tvzero.tv_usec = 0;
3731335f7552Schristos 		n = select(maxactivefd + 1, &fds, NULL, NULL, &tvzero);
3732335f7552Schristos 	}
3733335f7552Schristos 	if (n > 0)
3734335f7552Schristos 		input_handler_scan(cts, &fds);
3735335f7552Schristos }
3736335f7552Schristos #endif /* HAVE_SIGNALED_IO */
3737335f7552Schristos 
3738335f7552Schristos 
3739335f7552Schristos /*
3740335f7552Schristos  * Try to sanitize the global FD set
3741335f7552Schristos  *
3742335f7552Schristos  * SIGNAL HANDLER CONTEXT if HAVE_SIGNALED_IO, ordinary userspace otherwise
3743335f7552Schristos  */
3744335f7552Schristos static int/*BOOL*/
3745335f7552Schristos sanitize_fdset(
3746335f7552Schristos 	int	errc
3747335f7552Schristos 	)
3748335f7552Schristos {
3749335f7552Schristos 	int j, b, maxscan;
3750335f7552Schristos 
3751335f7552Schristos #  ifndef HAVE_SIGNALED_IO
3752335f7552Schristos 	/*
3753335f7552Schristos 	 * extended FAU debugging output
3754335f7552Schristos 	 */
3755335f7552Schristos 	if (errc != EINTR) {
3756335f7552Schristos 		msyslog(LOG_ERR,
3757335f7552Schristos 			"select(%d, %s, 0L, 0L, &0.0) error: %m",
3758335f7552Schristos 			maxactivefd + 1,
3759335f7552Schristos 			fdbits(maxactivefd, &activefds));
3760335f7552Schristos 	}
3761335f7552Schristos #   endif
3762335f7552Schristos 
3763335f7552Schristos 	if (errc != EBADF)
3764335f7552Schristos 		return FALSE;
3765335f7552Schristos 
3766335f7552Schristos 	/* if we have oviously bad FDs, try to sanitize the FD set. */
3767335f7552Schristos 	for (j = 0, maxscan = 0; j <= maxactivefd; j++) {
3768335f7552Schristos 		if (FD_ISSET(j, &activefds)) {
3769335f7552Schristos 			if (-1 != read(j, &b, 0)) {
3770335f7552Schristos 				maxscan = j;
3771335f7552Schristos 				continue;
3772335f7552Schristos 			}
3773335f7552Schristos #		    ifndef HAVE_SIGNALED_IO
3774335f7552Schristos 			msyslog(LOG_ERR,
3775335f7552Schristos 				"Removing bad file descriptor %d from select set",
3776335f7552Schristos 				j);
3777335f7552Schristos #		    endif
3778335f7552Schristos 			FD_CLR(j, &activefds);
3779335f7552Schristos 		}
3780335f7552Schristos 	}
3781335f7552Schristos 	if (maxactivefd != maxscan)
3782335f7552Schristos 		maxactivefd = maxscan;
3783335f7552Schristos 	return TRUE;
3784335f7552Schristos }
3785335f7552Schristos 
3786335f7552Schristos /*
3787335f7552Schristos  * scan the known FDs (clocks, servers, ...) for presence in a 'fd_set'.
3788335f7552Schristos  *
3789335f7552Schristos  * SIGNAL HANDLER CONTEXT if HAVE_SIGNALED_IO, ordinary userspace otherwise
3790335f7552Schristos  */
3791335f7552Schristos static void
3792335f7552Schristos input_handler_scan(
3793335f7552Schristos 	const l_fp *	cts,
3794335f7552Schristos 	const fd_set *	pfds
3795335f7552Schristos 	)
3796335f7552Schristos {
3797335f7552Schristos 	int		buflen;
3798b3d6264cSchristos 	u_int		idx;
3799abb0f93cSkardel 	int		doing;
3800abb0f93cSkardel 	SOCKET		fd;
3801b3d6264cSchristos 	blocking_child *c;
3802abb0f93cSkardel 	l_fp		ts;	/* Timestamp at BOselect() gob */
3803335f7552Schristos 
3804335f7552Schristos #if defined(DEBUG_TIMING)
3805abb0f93cSkardel 	l_fp		ts_e;	/* Timestamp at EOselect() gob */
3806abb0f93cSkardel #endif
380745530cf1Skardel 	endpt *		ep;
3808b3d6264cSchristos #ifdef REFCLOCK
3809b3d6264cSchristos 	struct refclockio *rp;
3810b3d6264cSchristos 	int		saved_errno;
3811b3d6264cSchristos 	const char *	clk;
3812b3d6264cSchristos #endif
3813b3d6264cSchristos #ifdef HAS_ROUTING_SOCKET
3814abb0f93cSkardel 	struct asyncio_reader *	asyncio_reader;
3815b3d6264cSchristos 	struct asyncio_reader *	next_asyncio_reader;
3816abb0f93cSkardel #endif
3817abb0f93cSkardel 
3818abb0f93cSkardel 	++handler_pkts;
3819335f7552Schristos 	ts = *cts;
3820abb0f93cSkardel 
3821abb0f93cSkardel #ifdef REFCLOCK
3822abb0f93cSkardel 	/*
3823abb0f93cSkardel 	 * Check out the reference clocks first, if any
3824abb0f93cSkardel 	 */
3825abb0f93cSkardel 
3826abb0f93cSkardel 	for (rp = refio; rp != NULL; rp = rp->next) {
3827abb0f93cSkardel 		fd = rp->fd;
3828abb0f93cSkardel 
3829335f7552Schristos 		if (!FD_ISSET(fd, pfds))
3830b3d6264cSchristos 			continue;
3831b3d6264cSchristos 		buflen = read_refclock_packet(fd, rp, ts);
3832b3d6264cSchristos 		/*
3833335f7552Schristos 		 * The first read must succeed after select() indicates
3834335f7552Schristos 		 * readability, or we've reached a permanent EOF.
3835335f7552Schristos 		 * http://bugs.ntp.org/1732 reported ntpd munching CPU
3836335f7552Schristos 		 * after a USB GPS was unplugged because select was
3837335f7552Schristos 		 * indicating EOF but ntpd didn't remove the descriptor
3838b3d6264cSchristos 		 * from the activefds set.
3839b3d6264cSchristos 		 */
3840b3d6264cSchristos 		if (buflen < 0 && EAGAIN != errno) {
3841b3d6264cSchristos 			saved_errno = errno;
3842b3d6264cSchristos 			clk = refnumtoa(&rp->srcclock->srcadr);
3843b3d6264cSchristos 			errno = saved_errno;
3844b3d6264cSchristos 			msyslog(LOG_ERR, "%s read: %m", clk);
3845b3d6264cSchristos 			maintain_activefds(fd, TRUE);
3846b3d6264cSchristos 		} else if (0 == buflen) {
3847b3d6264cSchristos 			clk = refnumtoa(&rp->srcclock->srcadr);
3848b3d6264cSchristos 			msyslog(LOG_ERR, "%s read EOF", clk);
3849b3d6264cSchristos 			maintain_activefds(fd, TRUE);
3850b3d6264cSchristos 		} else {
3851b3d6264cSchristos 			/* drain any remaining refclock input */
3852b3d6264cSchristos 			do {
3853b3d6264cSchristos 				buflen = read_refclock_packet(fd, rp, ts);
3854abb0f93cSkardel 			} while (buflen > 0);
3855abb0f93cSkardel 		}
3856abb0f93cSkardel 	}
3857abb0f93cSkardel #endif /* REFCLOCK */
3858abb0f93cSkardel 
3859abb0f93cSkardel 	/*
3860abb0f93cSkardel 	 * Loop through the interfaces looking for data to read.
3861abb0f93cSkardel 	 */
386245530cf1Skardel 	for (ep = ep_list; ep != NULL; ep = ep->elink) {
386345530cf1Skardel 		for (doing = 0; doing < 2; doing++) {
386445530cf1Skardel 			if (!doing) {
386545530cf1Skardel 				fd = ep->fd;
386645530cf1Skardel 			} else {
386745530cf1Skardel 				if (!(ep->flags & INT_BCASTOPEN))
3868abb0f93cSkardel 					break;
386945530cf1Skardel 				fd = ep->bfd;
3870abb0f93cSkardel 			}
3871abb0f93cSkardel 			if (fd < 0)
3872abb0f93cSkardel 				continue;
3873335f7552Schristos 			if (FD_ISSET(fd, pfds))
3874abb0f93cSkardel 				do {
3875abb0f93cSkardel 					buflen = read_network_packet(
387645530cf1Skardel 							fd, ep, ts);
3877abb0f93cSkardel 				} while (buflen > 0);
3878abb0f93cSkardel 			/* Check more interfaces */
3879abb0f93cSkardel 		}
3880abb0f93cSkardel 	}
3881abb0f93cSkardel 
3882abb0f93cSkardel #ifdef HAS_ROUTING_SOCKET
3883abb0f93cSkardel 	/*
3884abb0f93cSkardel 	 * scan list of asyncio readers - currently only used for routing sockets
3885abb0f93cSkardel 	 */
3886abb0f93cSkardel 	asyncio_reader = asyncio_reader_list;
3887abb0f93cSkardel 
3888abb0f93cSkardel 	while (asyncio_reader != NULL) {
3889b3d6264cSchristos 		/* callback may unlink and free asyncio_reader */
3890b3d6264cSchristos 		next_asyncio_reader = asyncio_reader->link;
3891335f7552Schristos 		if (FD_ISSET(asyncio_reader->fd, pfds))
3892b3d6264cSchristos 			(*asyncio_reader->receiver)(asyncio_reader);
3893b3d6264cSchristos 		asyncio_reader = next_asyncio_reader;
3894abb0f93cSkardel 	}
3895abb0f93cSkardel #endif /* HAS_ROUTING_SOCKET */
3896abb0f93cSkardel 
3897abb0f93cSkardel 	/*
3898b3d6264cSchristos 	 * Check for a response from a blocking child
3899abb0f93cSkardel 	 */
3900b3d6264cSchristos 	for (idx = 0; idx < blocking_children_alloc; idx++) {
3901b3d6264cSchristos 		c = blocking_children[idx];
3902b3d6264cSchristos 		if (NULL == c || -1 == c->resp_read_pipe)
3903b3d6264cSchristos 			continue;
3904335f7552Schristos 		if (FD_ISSET(c->resp_read_pipe, pfds)) {
3905335f7552Schristos 			++c->resp_ready_seen;
3906335f7552Schristos 			++blocking_child_ready_seen;
3907b3d6264cSchristos 		}
3908b3d6264cSchristos 	}
3909abb0f93cSkardel 
3910abb0f93cSkardel 	/* We've done our work */
3911335f7552Schristos #if defined(DEBUG_TIMING)
3912abb0f93cSkardel 	get_systime(&ts_e);
3913abb0f93cSkardel 	/*
3914abb0f93cSkardel 	 * (ts_e - ts) is the amount of time we spent
3915abb0f93cSkardel 	 * processing this gob of file descriptors.  Log
3916abb0f93cSkardel 	 * it.
3917abb0f93cSkardel 	 */
3918abb0f93cSkardel 	L_SUB(&ts_e, &ts);
3919abb0f93cSkardel 	collect_timing(NULL, "input handler", 1, &ts_e);
3920abb0f93cSkardel 	if (debug > 3)
3921abb0f93cSkardel 		msyslog(LOG_DEBUG,
3922abb0f93cSkardel 			"input_handler: Processed a gob of fd's in %s msec",
3923abb0f93cSkardel 			lfptoms(&ts_e, 6));
3924b3d6264cSchristos #endif /* DEBUG_TIMING */
3925abb0f93cSkardel }
3926b3d6264cSchristos #endif /* !HAVE_IO_COMPLETION_PORT */
3927b3d6264cSchristos 
3928b3d6264cSchristos /*
3929b3d6264cSchristos  * find an interface suitable for the src address
3930b3d6264cSchristos  */
3931b3d6264cSchristos endpt *
3932b3d6264cSchristos select_peerinterface(
3933b3d6264cSchristos 	struct peer *	peer,
3934b3d6264cSchristos 	sockaddr_u *	srcadr,
3935b3d6264cSchristos 	endpt *		dstadr
3936b3d6264cSchristos 	)
3937b3d6264cSchristos {
3938b3d6264cSchristos 	endpt *ep;
3939b3d6264cSchristos #ifndef SIM
3940b3d6264cSchristos 	endpt *wild;
3941b3d6264cSchristos 
3942b3d6264cSchristos 	wild = ANY_INTERFACE_CHOOSE(srcadr);
3943b3d6264cSchristos 
3944b3d6264cSchristos 	/*
3945b3d6264cSchristos 	 * Initialize the peer structure and dance the interface jig.
3946b3d6264cSchristos 	 * Reference clocks step the loopback waltz, the others
3947b3d6264cSchristos 	 * squaredance around the interface list looking for a buddy. If
3948b3d6264cSchristos 	 * the dance peters out, there is always the wildcard interface.
3949b3d6264cSchristos 	 * This might happen in some systems and would preclude proper
3950b3d6264cSchristos 	 * operation with public key cryptography.
3951b3d6264cSchristos 	 */
3952b3d6264cSchristos 	if (ISREFCLOCKADR(srcadr)) {
3953b3d6264cSchristos 		ep = loopback_interface;
3954b3d6264cSchristos 	} else if (peer->cast_flags &
3955b3d6264cSchristos 		   (MDF_BCLNT | MDF_ACAST | MDF_MCAST | MDF_BCAST)) {
3956b3d6264cSchristos 		ep = findbcastinter(srcadr);
3957b3d6264cSchristos 		if (ep != NULL)
3958b3d6264cSchristos 			DPRINTF(4, ("Found *-cast interface %s for address %s\n",
3959b3d6264cSchristos 				stoa(&ep->sin), stoa(srcadr)));
3960b3d6264cSchristos 		else
3961b3d6264cSchristos 			DPRINTF(4, ("No *-cast local address found for address %s\n",
3962b3d6264cSchristos 				stoa(srcadr)));
3963b3d6264cSchristos 	} else {
3964b3d6264cSchristos 		ep = dstadr;
3965b3d6264cSchristos 		if (NULL == ep)
3966b3d6264cSchristos 			ep = wild;
3967b3d6264cSchristos 	}
3968b3d6264cSchristos 	/*
3969b3d6264cSchristos 	 * If it is a multicast address, findbcastinter() may not find
3970b3d6264cSchristos 	 * it.  For unicast, we get to find the interface when dstadr is
3971b3d6264cSchristos 	 * given to us as the wildcard (ANY_INTERFACE_CHOOSE).  Either
3972b3d6264cSchristos 	 * way, try a little harder.
3973b3d6264cSchristos 	 */
3974b3d6264cSchristos 	if (wild == ep)
3975b3d6264cSchristos 		ep = findinterface(srcadr);
3976b3d6264cSchristos 	/*
3977b3d6264cSchristos 	 * we do not bind to the wildcard interfaces for output
3978b3d6264cSchristos 	 * as our (network) source address would be undefined and
3979b3d6264cSchristos 	 * crypto will not work without knowing the own transmit address
3980b3d6264cSchristos 	 */
3981b3d6264cSchristos 	if (ep != NULL && INT_WILDCARD & ep->flags)
3982b3d6264cSchristos 		if (!accept_wildcard_if_for_winnt)
3983b3d6264cSchristos 			ep = NULL;
3984b3d6264cSchristos #else	/* SIM follows */
3985b3d6264cSchristos 	ep = loopback_interface;
3986abb0f93cSkardel #endif
3987abb0f93cSkardel 
3988b3d6264cSchristos 	return ep;
3989b3d6264cSchristos }
3990b3d6264cSchristos 
3991b3d6264cSchristos 
3992abb0f93cSkardel /*
3993abb0f93cSkardel  * findinterface - find local interface corresponding to address
3994abb0f93cSkardel  */
399545530cf1Skardel endpt *
3996abb0f93cSkardel findinterface(
3997abb0f93cSkardel 	sockaddr_u *addr
3998abb0f93cSkardel 	)
3999abb0f93cSkardel {
400045530cf1Skardel 	endpt *iface;
4001abb0f93cSkardel 
4002abb0f93cSkardel 	iface = findlocalinterface(addr, INT_WILDCARD, 0);
4003abb0f93cSkardel 
4004abb0f93cSkardel 	if (NULL == iface) {
4005abb0f93cSkardel 		DPRINTF(4, ("Found no interface for address %s - returning wildcard\n",
4006abb0f93cSkardel 			    stoa(addr)));
4007abb0f93cSkardel 
4008abb0f93cSkardel 		iface = ANY_INTERFACE_CHOOSE(addr);
4009abb0f93cSkardel 	} else
4010abb0f93cSkardel 		DPRINTF(4, ("Found interface #%d %s for address %s\n",
4011abb0f93cSkardel 			    iface->ifnum, iface->name, stoa(addr)));
4012abb0f93cSkardel 
4013abb0f93cSkardel 	return iface;
4014abb0f93cSkardel }
4015abb0f93cSkardel 
4016abb0f93cSkardel /*
4017abb0f93cSkardel  * findlocalinterface - find local interface corresponding to addr,
4018abb0f93cSkardel  * which does not have any of flags set.  If bast is nonzero, addr is
4019abb0f93cSkardel  * a broadcast address.
4020abb0f93cSkardel  *
4021abb0f93cSkardel  * This code attempts to find the local sending address for an outgoing
4022abb0f93cSkardel  * address by connecting a new socket to destinationaddress:NTP_PORT
4023abb0f93cSkardel  * and reading the sockname of the resulting connect.
4024abb0f93cSkardel  * the complicated sequence simulates the routing table lookup
4025abb0f93cSkardel  * for to first hop without duplicating any of the routing logic into
4026abb0f93cSkardel  * ntpd. preferably we would have used an API call - but its not there -
4027abb0f93cSkardel  * so this is the best we can do here short of duplicating to entire routing
4028abb0f93cSkardel  * logic in ntpd which would be a silly and really unportable thing to do.
4029abb0f93cSkardel  *
4030abb0f93cSkardel  */
403145530cf1Skardel static endpt *
4032abb0f93cSkardel findlocalinterface(
4033abb0f93cSkardel 	sockaddr_u *	addr,
4034abb0f93cSkardel 	int		flags,
4035abb0f93cSkardel 	int		bcast
4036abb0f93cSkardel 	)
4037abb0f93cSkardel {
4038abb0f93cSkardel 	GETSOCKNAME_SOCKLEN_TYPE	sockaddrlen;
403945530cf1Skardel 	endpt *				iface;
4040abb0f93cSkardel 	sockaddr_u			saddr;
4041abb0f93cSkardel 	SOCKET				s;
4042abb0f93cSkardel 	int				rtn;
4043abb0f93cSkardel 	int				on;
4044abb0f93cSkardel 
4045abb0f93cSkardel 	DPRINTF(4, ("Finding interface for addr %s in list of addresses\n",
4046abb0f93cSkardel 		    stoa(addr)));
4047abb0f93cSkardel 
4048169394abSchristos 	/* [Bug 3437] The dummy POOL peer comes in with an AF of
4049169394abSchristos 	 * zero. This is bound to fail, but on the way to nowhere it
4050169394abSchristos 	 * triggers a security incident on SELinux.
4051169394abSchristos 	 *
4052169394abSchristos 	 * Checking the condition and failing early is probably a good
4053169394abSchristos 	 * advice, and even saves us some syscalls in that case.
4054169394abSchristos 	 * Thanks to Miroslav Lichvar for finding this.
4055169394abSchristos 	 */
4056169394abSchristos 	if (AF_UNSPEC == AF(addr))
4057169394abSchristos 		return NULL;
4058169394abSchristos 
4059abb0f93cSkardel 	s = socket(AF(addr), SOCK_DGRAM, 0);
4060abb0f93cSkardel 	if (INVALID_SOCKET == s)
4061abb0f93cSkardel 		return NULL;
4062abb0f93cSkardel 
4063abb0f93cSkardel 	/*
4064abb0f93cSkardel 	 * If we are looking for broadcast interface we need to set this
4065abb0f93cSkardel 	 * socket to allow broadcast
4066abb0f93cSkardel 	 */
4067abb0f93cSkardel 	if (bcast) {
4068abb0f93cSkardel 		on = 1;
4069b3d6264cSchristos 		if (SOCKET_ERROR == setsockopt(s, SOL_SOCKET,
4070b3d6264cSchristos 						SO_BROADCAST,
4071169394abSchristos 						(void *)&on,
4072b3d6264cSchristos 						sizeof(on))) {
4073b3d6264cSchristos 			closesocket(s);
4074b3d6264cSchristos 			return NULL;
4075b3d6264cSchristos 		}
4076abb0f93cSkardel 	}
4077abb0f93cSkardel 
4078abb0f93cSkardel 	rtn = connect(s, &addr->sa, SOCKLEN(addr));
4079abb0f93cSkardel 	if (SOCKET_ERROR == rtn) {
4080abb0f93cSkardel 		closesocket(s);
4081abb0f93cSkardel 		return NULL;
4082abb0f93cSkardel 	}
4083abb0f93cSkardel 
4084abb0f93cSkardel 	sockaddrlen = sizeof(saddr);
4085abb0f93cSkardel 	rtn = getsockname(s, &saddr.sa, &sockaddrlen);
4086abb0f93cSkardel 	closesocket(s);
4087abb0f93cSkardel 	if (SOCKET_ERROR == rtn)
4088abb0f93cSkardel 		return NULL;
4089abb0f93cSkardel 
4090abb0f93cSkardel 	DPRINTF(4, ("findlocalinterface: kernel maps %s to %s\n",
4091abb0f93cSkardel 		    stoa(addr), stoa(&saddr)));
4092abb0f93cSkardel 
4093abb0f93cSkardel 	iface = getinterface(&saddr, flags);
4094abb0f93cSkardel 
4095abb0f93cSkardel 	/*
409645530cf1Skardel 	 * if we didn't find an exact match on saddr, find the closest
409745530cf1Skardel 	 * available local address.  This handles the case of the
409845530cf1Skardel 	 * address suggested by the kernel being excluded by nic rules
409945530cf1Skardel 	 * or the user's -I and -L options to ntpd.
410045530cf1Skardel 	 * See http://bugs.ntp.org/1184 and http://bugs.ntp.org/1683
410145530cf1Skardel 	 * for more background.
4102abb0f93cSkardel 	 */
4103abb0f93cSkardel 	if (NULL == iface || iface->ignore_packets)
410445530cf1Skardel 		iface = findclosestinterface(&saddr,
410545530cf1Skardel 					     flags | INT_LOOPBACK);
4106abb0f93cSkardel 
4107abb0f93cSkardel 	/* Don't use an interface which will ignore replies */
4108abb0f93cSkardel 	if (iface != NULL && iface->ignore_packets)
4109abb0f93cSkardel 		iface = NULL;
4110abb0f93cSkardel 
4111abb0f93cSkardel 	return iface;
4112abb0f93cSkardel }
4113abb0f93cSkardel 
4114abb0f93cSkardel 
4115abb0f93cSkardel /*
411645530cf1Skardel  * findclosestinterface
411745530cf1Skardel  *
411845530cf1Skardel  * If there are -I/--interface or -L/novirtualips command-line options,
411945530cf1Skardel  * or "nic" or "interface" rules in ntp.conf, findlocalinterface() may
412045530cf1Skardel  * find the kernel's preferred local address for a given peer address is
412145530cf1Skardel  * administratively unavailable to ntpd, and punt to this routine's more
412245530cf1Skardel  * expensive search.
412345530cf1Skardel  *
412445530cf1Skardel  * Find the numerically closest local address to the one connect()
412545530cf1Skardel  * suggested.  This matches an address on the same subnet first, as
412645530cf1Skardel  * needed by Bug 1184, and provides a consistent choice if there are
412745530cf1Skardel  * multiple feasible local addresses, regardless of the order ntpd
412845530cf1Skardel  * enumerated them.
4129abb0f93cSkardel  */
4130b3d6264cSchristos endpt *
413145530cf1Skardel findclosestinterface(
4132abb0f93cSkardel 	sockaddr_u *	addr,
4133abb0f93cSkardel 	int		flags
4134abb0f93cSkardel 	)
4135abb0f93cSkardel {
413645530cf1Skardel 	endpt *		ep;
413745530cf1Skardel 	endpt *		winner;
413845530cf1Skardel 	sockaddr_u	addr_dist;
413945530cf1Skardel 	sockaddr_u	min_dist;
414045530cf1Skardel 
4141b3d6264cSchristos 	ZERO_SOCK(&min_dist);
414245530cf1Skardel 	winner = NULL;
414345530cf1Skardel 
414445530cf1Skardel 	for (ep = ep_list; ep != NULL; ep = ep->elink) {
414545530cf1Skardel 		if (ep->ignore_packets ||
414645530cf1Skardel 		    AF(addr) != ep->family ||
414745530cf1Skardel 		    flags & ep->flags)
414845530cf1Skardel 			continue;
414945530cf1Skardel 
415045530cf1Skardel 		calc_addr_distance(&addr_dist, addr, &ep->sin);
415145530cf1Skardel 		if (NULL == winner ||
415245530cf1Skardel 		    -1 == cmp_addr_distance(&addr_dist, &min_dist)) {
415345530cf1Skardel 			min_dist = addr_dist;
415445530cf1Skardel 			winner = ep;
415545530cf1Skardel 		}
415645530cf1Skardel 	}
415745530cf1Skardel 	if (NULL == winner)
415845530cf1Skardel 		DPRINTF(4, ("findclosestinterface(%s) failed\n",
415945530cf1Skardel 			    stoa(addr)));
416045530cf1Skardel 	else
416145530cf1Skardel 		DPRINTF(4, ("findclosestinterface(%s) -> %s\n",
416245530cf1Skardel 			    stoa(addr), stoa(&winner->sin)));
416345530cf1Skardel 
416445530cf1Skardel 	return winner;
416545530cf1Skardel }
416645530cf1Skardel 
416745530cf1Skardel 
416845530cf1Skardel /*
416945530cf1Skardel  * calc_addr_distance - calculate the distance between two addresses,
417045530cf1Skardel  *			the absolute value of the difference between
417145530cf1Skardel  *			the addresses numerically, stored as an address.
417245530cf1Skardel  */
417345530cf1Skardel static void
417445530cf1Skardel calc_addr_distance(
417545530cf1Skardel 	sockaddr_u *		dist,
417645530cf1Skardel 	const sockaddr_u *	a1,
417745530cf1Skardel 	const sockaddr_u *	a2
417845530cf1Skardel 	)
417945530cf1Skardel {
418045530cf1Skardel 	u_int32	a1val;
418145530cf1Skardel 	u_int32	a2val;
418245530cf1Skardel 	u_int32	v4dist;
418345530cf1Skardel 	int	found_greater;
418445530cf1Skardel 	int	a1_greater;
418545530cf1Skardel 	int	i;
418645530cf1Skardel 
418709f14f80Schristos 	REQUIRE(AF(a1) == AF(a2));
418845530cf1Skardel 
4189b3d6264cSchristos 	ZERO_SOCK(dist);
419045530cf1Skardel 	AF(dist) = AF(a1);
419145530cf1Skardel 
419245530cf1Skardel 	/* v4 can be done a bit simpler */
419345530cf1Skardel 	if (IS_IPV4(a1)) {
419445530cf1Skardel 		a1val = SRCADR(a1);
419545530cf1Skardel 		a2val = SRCADR(a2);
419645530cf1Skardel 		v4dist = (a1val > a2val)
419745530cf1Skardel 			     ? a1val - a2val
419845530cf1Skardel 			     : a2val - a1val;
419945530cf1Skardel 		SET_ADDR4(dist, v4dist);
420045530cf1Skardel 
420145530cf1Skardel 		return;
420245530cf1Skardel 	}
420345530cf1Skardel 
420445530cf1Skardel 	found_greater = FALSE;
420545530cf1Skardel 	a1_greater = FALSE;	/* suppress pot. uninit. warning */
4206f40817b7Skardel 	for (i = 0; i < (int)sizeof(NSRCADR6(a1)); i++) {
420745530cf1Skardel 		if (!found_greater &&
420845530cf1Skardel 		    NSRCADR6(a1)[i] != NSRCADR6(a2)[i]) {
420945530cf1Skardel 			found_greater = TRUE;
421045530cf1Skardel 			a1_greater = (NSRCADR6(a1)[i] > NSRCADR6(a2)[i]);
421145530cf1Skardel 		}
421245530cf1Skardel 		if (!found_greater) {
421345530cf1Skardel 			NSRCADR6(dist)[i] = 0;
421445530cf1Skardel 		} else {
421545530cf1Skardel 			if (a1_greater)
421645530cf1Skardel 				NSRCADR6(dist)[i] = NSRCADR6(a1)[i] -
421745530cf1Skardel 						    NSRCADR6(a2)[i];
421845530cf1Skardel 			else
421945530cf1Skardel 				NSRCADR6(dist)[i] = NSRCADR6(a2)[i] -
422045530cf1Skardel 						    NSRCADR6(a1)[i];
422145530cf1Skardel 		}
422245530cf1Skardel 	}
422345530cf1Skardel }
422445530cf1Skardel 
422545530cf1Skardel 
422645530cf1Skardel /*
422745530cf1Skardel  * cmp_addr_distance - compare two address distances, returning -1, 0,
422845530cf1Skardel  *		       1 to indicate their relationship.
422945530cf1Skardel  */
423045530cf1Skardel static int
423145530cf1Skardel cmp_addr_distance(
423245530cf1Skardel 	const sockaddr_u *	d1,
423345530cf1Skardel 	const sockaddr_u *	d2
423445530cf1Skardel 	)
423545530cf1Skardel {
423645530cf1Skardel 	int	i;
423745530cf1Skardel 
423809f14f80Schristos 	REQUIRE(AF(d1) == AF(d2));
423945530cf1Skardel 
424045530cf1Skardel 	if (IS_IPV4(d1)) {
424145530cf1Skardel 		if (SRCADR(d1) < SRCADR(d2))
424245530cf1Skardel 			return -1;
424345530cf1Skardel 		else if (SRCADR(d1) == SRCADR(d2))
424445530cf1Skardel 			return 0;
424545530cf1Skardel 		else
424645530cf1Skardel 			return 1;
424745530cf1Skardel 	}
424845530cf1Skardel 
4249f40817b7Skardel 	for (i = 0; i < (int)sizeof(NSRCADR6(d1)); i++) {
425045530cf1Skardel 		if (NSRCADR6(d1)[i] < NSRCADR6(d2)[i])
425145530cf1Skardel 			return -1;
425245530cf1Skardel 		else if (NSRCADR6(d1)[i] > NSRCADR6(d2)[i])
425345530cf1Skardel 			return 1;
425445530cf1Skardel 	}
425545530cf1Skardel 
425645530cf1Skardel 	return 0;
425745530cf1Skardel }
425845530cf1Skardel 
425945530cf1Skardel 
426045530cf1Skardel 
426145530cf1Skardel /*
426245530cf1Skardel  * fetch an interface structure the matches the
426345530cf1Skardel  * address and has the given flags NOT set
426445530cf1Skardel  */
4265b3d6264cSchristos endpt *
426645530cf1Skardel getinterface(
426745530cf1Skardel 	sockaddr_u *	addr,
426845530cf1Skardel 	u_int32		flags
426945530cf1Skardel 	)
427045530cf1Skardel {
427145530cf1Skardel 	endpt *iface;
4272abb0f93cSkardel 
4273abb0f93cSkardel 	iface = find_addr_in_list(addr);
4274abb0f93cSkardel 
4275abb0f93cSkardel 	if (iface != NULL && (iface->flags & flags))
4276abb0f93cSkardel 		iface = NULL;
4277abb0f93cSkardel 
4278abb0f93cSkardel 	return iface;
4279abb0f93cSkardel }
4280abb0f93cSkardel 
4281abb0f93cSkardel 
4282abb0f93cSkardel /*
4283abb0f93cSkardel  * findbcastinter - find broadcast interface corresponding to address
4284abb0f93cSkardel  */
428545530cf1Skardel endpt *
4286abb0f93cSkardel findbcastinter(
4287abb0f93cSkardel 	sockaddr_u *addr
4288abb0f93cSkardel 	)
4289abb0f93cSkardel {
4290b3d6264cSchristos 	endpt *	iface;
4291b3d6264cSchristos 
4292b3d6264cSchristos 	iface = NULL;
4293abb0f93cSkardel #if !defined(MPE) && (defined(SIOCGIFCONF) || defined(SYS_WINNT))
4294abb0f93cSkardel 	DPRINTF(4, ("Finding broadcast/multicast interface for addr %s in list of addresses\n",
4295abb0f93cSkardel 		    stoa(addr)));
4296abb0f93cSkardel 
4297abb0f93cSkardel 	iface = findlocalinterface(addr, INT_LOOPBACK | INT_WILDCARD,
4298abb0f93cSkardel 				   1);
4299abb0f93cSkardel 	if (iface != NULL) {
4300abb0f93cSkardel 		DPRINTF(4, ("Easily found bcast-/mcast- interface index #%d %s\n",
4301abb0f93cSkardel 			    iface->ifnum, iface->name));
4302abb0f93cSkardel 		return iface;
4303abb0f93cSkardel 	}
4304abb0f93cSkardel 
4305abb0f93cSkardel 	/*
4306abb0f93cSkardel 	 * plan B - try to find something reasonable in our lists in
4307abb0f93cSkardel 	 * case kernel lookup doesn't help
4308abb0f93cSkardel 	 */
430945530cf1Skardel 	for (iface = ep_list; iface != NULL; iface = iface->elink) {
4310abb0f93cSkardel 		if (iface->flags & INT_WILDCARD)
4311abb0f93cSkardel 			continue;
4312abb0f93cSkardel 
4313abb0f93cSkardel 		/* Don't bother with ignored interfaces */
4314abb0f93cSkardel 		if (iface->ignore_packets)
4315abb0f93cSkardel 			continue;
4316abb0f93cSkardel 
4317abb0f93cSkardel 		/*
4318abb0f93cSkardel 		 * First look if this is the correct family
4319abb0f93cSkardel 		 */
4320abb0f93cSkardel 		if(AF(&iface->sin) != AF(addr))
4321abb0f93cSkardel 			continue;
4322abb0f93cSkardel 
4323abb0f93cSkardel 		/* Skip the loopback addresses */
4324abb0f93cSkardel 		if (iface->flags & INT_LOOPBACK)
4325abb0f93cSkardel 			continue;
4326abb0f93cSkardel 
4327abb0f93cSkardel 		/*
4328abb0f93cSkardel 		 * If we are looking to match a multicast address and
4329abb0f93cSkardel 		 * this interface is one...
4330abb0f93cSkardel 		 */
4331abb0f93cSkardel 		if (addr_ismulticast(addr)
4332abb0f93cSkardel 		    && (iface->flags & INT_MULTICAST)) {
4333abb0f93cSkardel #ifdef INCLUDE_IPV6_SUPPORT
4334abb0f93cSkardel 			/*
4335abb0f93cSkardel 			 * ...it is the winner unless we're looking for
4336abb0f93cSkardel 			 * an interface to use for link-local multicast
4337abb0f93cSkardel 			 * and its address is not link-local.
4338abb0f93cSkardel 			 */
4339abb0f93cSkardel 			if (IS_IPV6(addr)
4340abb0f93cSkardel 			    && IN6_IS_ADDR_MC_LINKLOCAL(PSOCK_ADDR6(addr))
4341abb0f93cSkardel 			    && !IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(&iface->sin)))
4342abb0f93cSkardel 				continue;
4343abb0f93cSkardel #endif
4344abb0f93cSkardel 			break;
4345abb0f93cSkardel 		}
4346abb0f93cSkardel 
4347abb0f93cSkardel 		/*
4348abb0f93cSkardel 		 * We match only those interfaces marked as
4349abb0f93cSkardel 		 * broadcastable and either the explicit broadcast
4350abb0f93cSkardel 		 * address or the network portion of the IP address.
4351abb0f93cSkardel 		 * Sloppy.
4352abb0f93cSkardel 		 */
4353abb0f93cSkardel 		if (IS_IPV4(addr)) {
4354abb0f93cSkardel 			if (SOCK_EQ(&iface->bcast, addr))
4355abb0f93cSkardel 				break;
4356abb0f93cSkardel 
4357abb0f93cSkardel 			if ((NSRCADR(&iface->sin) & NSRCADR(&iface->mask))
4358abb0f93cSkardel 			    == (NSRCADR(addr)	  & NSRCADR(&iface->mask)))
4359abb0f93cSkardel 				break;
4360abb0f93cSkardel 		}
4361abb0f93cSkardel #ifdef INCLUDE_IPV6_SUPPORT
4362abb0f93cSkardel 		else if (IS_IPV6(addr)) {
4363abb0f93cSkardel 			if (SOCK_EQ(&iface->bcast, addr))
4364abb0f93cSkardel 				break;
4365abb0f93cSkardel 
4366abb0f93cSkardel 			if (SOCK_EQ(netof(&iface->sin), netof(addr)))
4367abb0f93cSkardel 				break;
4368abb0f93cSkardel 		}
4369abb0f93cSkardel #endif
4370abb0f93cSkardel 	}
4371abb0f93cSkardel #endif /* SIOCGIFCONF */
4372abb0f93cSkardel 	if (NULL == iface) {
4373abb0f93cSkardel 		DPRINTF(4, ("No bcast interface found for %s\n",
4374abb0f93cSkardel 			    stoa(addr)));
4375abb0f93cSkardel 		iface = ANY_INTERFACE_CHOOSE(addr);
4376b3d6264cSchristos 	} else {
4377abb0f93cSkardel 		DPRINTF(4, ("Found bcast-/mcast- interface index #%d %s\n",
4378abb0f93cSkardel 			    iface->ifnum, iface->name));
4379b3d6264cSchristos 	}
4380b3d6264cSchristos 
4381abb0f93cSkardel 	return iface;
4382abb0f93cSkardel }
4383abb0f93cSkardel 
4384abb0f93cSkardel 
4385abb0f93cSkardel /*
4386abb0f93cSkardel  * io_clr_stats - clear I/O module statistics
4387abb0f93cSkardel  */
4388abb0f93cSkardel void
4389abb0f93cSkardel io_clr_stats(void)
4390abb0f93cSkardel {
4391abb0f93cSkardel 	packets_dropped = 0;
4392abb0f93cSkardel 	packets_ignored = 0;
4393abb0f93cSkardel 	packets_received = 0;
4394abb0f93cSkardel 	packets_sent = 0;
4395abb0f93cSkardel 	packets_notsent = 0;
4396abb0f93cSkardel 
4397abb0f93cSkardel 	handler_calls = 0;
4398abb0f93cSkardel 	handler_pkts = 0;
4399abb0f93cSkardel 	io_timereset = current_time;
4400abb0f93cSkardel }
4401abb0f93cSkardel 
4402abb0f93cSkardel 
4403abb0f93cSkardel #ifdef REFCLOCK
4404abb0f93cSkardel /*
4405abb0f93cSkardel  * io_addclock - add a reference clock to the list and arrange that we
4406abb0f93cSkardel  *				 get SIGIO interrupts from it.
4407abb0f93cSkardel  */
4408abb0f93cSkardel int
4409abb0f93cSkardel io_addclock(
4410abb0f93cSkardel 	struct refclockio *rio
4411abb0f93cSkardel 	)
4412abb0f93cSkardel {
4413abb0f93cSkardel 	BLOCKIO();
4414abb0f93cSkardel 
4415abb0f93cSkardel 	/*
4416abb0f93cSkardel 	 * Stuff the I/O structure in the list and mark the descriptor
4417abb0f93cSkardel 	 * in use.  There is a harmless (I hope) race condition here.
4418abb0f93cSkardel 	 */
4419b3d6264cSchristos 	rio->active = TRUE;
4420abb0f93cSkardel 
4421abb0f93cSkardel # ifdef HAVE_SIGNALED_IO
4422abb0f93cSkardel 	if (init_clock_sig(rio)) {
4423abb0f93cSkardel 		UNBLOCKIO();
4424abb0f93cSkardel 		return 0;
4425abb0f93cSkardel 	}
4426abb0f93cSkardel # elif defined(HAVE_IO_COMPLETION_PORT)
4427335f7552Schristos 	if (!io_completion_port_add_clock_io(rio)) {
4428abb0f93cSkardel 		UNBLOCKIO();
4429abb0f93cSkardel 		return 0;
4430abb0f93cSkardel 	}
4431abb0f93cSkardel # endif
4432abb0f93cSkardel 
4433abb0f93cSkardel 	/*
4434abb0f93cSkardel 	 * enqueue
4435abb0f93cSkardel 	 */
4436b3d6264cSchristos 	LINK_SLIST(refio, rio, next);
4437abb0f93cSkardel 
4438abb0f93cSkardel 	/*
4439abb0f93cSkardel 	 * register fd
4440abb0f93cSkardel 	 */
4441abb0f93cSkardel 	add_fd_to_list(rio->fd, FD_TYPE_FILE);
4442abb0f93cSkardel 
4443abb0f93cSkardel 	UNBLOCKIO();
4444abb0f93cSkardel 	return 1;
4445abb0f93cSkardel }
4446abb0f93cSkardel 
4447b3d6264cSchristos 
4448abb0f93cSkardel /*
4449abb0f93cSkardel  * io_closeclock - close the clock in the I/O structure given
4450abb0f93cSkardel  */
4451abb0f93cSkardel void
4452abb0f93cSkardel io_closeclock(
4453abb0f93cSkardel 	struct refclockio *rio
4454abb0f93cSkardel 	)
4455abb0f93cSkardel {
4456b3d6264cSchristos 	struct refclockio *unlinked;
4457abb0f93cSkardel 
4458abb0f93cSkardel 	BLOCKIO();
4459abb0f93cSkardel 
4460abb0f93cSkardel 	/*
4461abb0f93cSkardel 	 * Remove structure from the list
4462abb0f93cSkardel 	 */
4463b3d6264cSchristos 	rio->active = FALSE;
4464b3d6264cSchristos 	UNLINK_SLIST(unlinked, refio, rio, next, struct refclockio);
4465b3d6264cSchristos 	if (NULL != unlinked) {
4466335f7552Schristos 		/* Close the descriptor. The order of operations is
4467335f7552Schristos 		 * important here in case of async / overlapped IO:
4468335f7552Schristos 		 * only after we have removed the clock from the
4469335f7552Schristos 		 * IO completion port we can be sure no further
4470335f7552Schristos 		 * input is queued. So...
4471335f7552Schristos 		 *  - we first disable feeding to the queu by removing
4472335f7552Schristos 		 *    the clock from the IO engine
4473335f7552Schristos 		 *  - close the file (which brings down any IO on it)
4474335f7552Schristos 		 *  - clear the buffer from results for this fd
4475abb0f93cSkardel 		 */
4476335f7552Schristos #	    ifdef HAVE_IO_COMPLETION_PORT
4477335f7552Schristos 		io_completion_port_remove_clock_io(rio);
4478335f7552Schristos #	    endif
4479abb0f93cSkardel 		close_and_delete_fd_from_list(rio->fd);
4480335f7552Schristos 		purge_recv_buffers_for_fd(rio->fd);
4481b3d6264cSchristos 		rio->fd = -1;
4482335f7552Schristos 	}
4483b3d6264cSchristos 
4484abb0f93cSkardel 	UNBLOCKIO();
4485abb0f93cSkardel }
4486abb0f93cSkardel #endif	/* REFCLOCK */
4487abb0f93cSkardel 
4488b3d6264cSchristos 
4489abb0f93cSkardel /*
4490abb0f93cSkardel  * On NT a SOCKET is an unsigned int so we cannot possibly keep it in
4491abb0f93cSkardel  * an array. So we use one of the ISC_LIST functions to hold the
4492abb0f93cSkardel  * socket value and use that when we want to enumerate it.
4493abb0f93cSkardel  *
4494abb0f93cSkardel  * This routine is called by the forked intres child process to close
4495abb0f93cSkardel  * all open sockets.  On Windows there's no need as intres runs in
4496abb0f93cSkardel  * the same process as a thread.
4497abb0f93cSkardel  */
4498abb0f93cSkardel #ifndef SYS_WINNT
4499abb0f93cSkardel void
4500b3d6264cSchristos kill_asyncio(
4501b3d6264cSchristos 	int	startfd
4502b3d6264cSchristos 	)
4503abb0f93cSkardel {
4504abb0f93cSkardel 	BLOCKIO();
4505abb0f93cSkardel 
4506abb0f93cSkardel 	/*
4507abb0f93cSkardel 	 * In the child process we do not maintain activefds and
4508abb0f93cSkardel 	 * maxactivefd.  Zeroing maxactivefd disables code which
4509abb0f93cSkardel 	 * maintains it in close_and_delete_fd_from_list().
4510abb0f93cSkardel 	 */
4511abb0f93cSkardel 	maxactivefd = 0;
4512abb0f93cSkardel 
4513abb0f93cSkardel 	while (fd_list != NULL)
4514abb0f93cSkardel 		close_and_delete_fd_from_list(fd_list->fd);
4515abb0f93cSkardel 
4516abb0f93cSkardel 	UNBLOCKIO();
4517abb0f93cSkardel }
4518abb0f93cSkardel #endif	/* !SYS_WINNT */
4519abb0f93cSkardel 
4520b3d6264cSchristos 
4521abb0f93cSkardel /*
4522abb0f93cSkardel  * Add and delete functions for the list of open sockets
4523abb0f93cSkardel  */
4524abb0f93cSkardel static void
4525abb0f93cSkardel add_fd_to_list(
4526abb0f93cSkardel 	SOCKET fd,
4527abb0f93cSkardel 	enum desc_type type
4528abb0f93cSkardel 	)
4529abb0f93cSkardel {
4530abb0f93cSkardel 	vsock_t *lsock = emalloc(sizeof(*lsock));
4531abb0f93cSkardel 
4532abb0f93cSkardel 	lsock->fd = fd;
4533abb0f93cSkardel 	lsock->type = type;
4534abb0f93cSkardel 
4535abb0f93cSkardel 	LINK_SLIST(fd_list, lsock, link);
4536b3d6264cSchristos 	maintain_activefds(fd, 0);
4537abb0f93cSkardel }
4538abb0f93cSkardel 
4539abb0f93cSkardel 
4540abb0f93cSkardel static void
4541abb0f93cSkardel close_and_delete_fd_from_list(
4542abb0f93cSkardel 	SOCKET fd
4543abb0f93cSkardel 	)
4544abb0f93cSkardel {
4545abb0f93cSkardel 	vsock_t *lsock;
4546abb0f93cSkardel 
4547abb0f93cSkardel 	UNLINK_EXPR_SLIST(lsock, fd_list, fd ==
4548abb0f93cSkardel 	    UNLINK_EXPR_SLIST_CURRENT()->fd, link, vsock_t);
4549abb0f93cSkardel 
4550b3d6264cSchristos 	if (NULL == lsock)
4551b3d6264cSchristos 		return;
4552b3d6264cSchristos 
4553abb0f93cSkardel 	switch (lsock->type) {
4554b3d6264cSchristos 
4555abb0f93cSkardel 	case FD_TYPE_SOCKET:
4556abb0f93cSkardel 		closesocket(lsock->fd);
4557abb0f93cSkardel 		break;
4558abb0f93cSkardel 
4559abb0f93cSkardel 	case FD_TYPE_FILE:
4560bd25f4c4Schristos 		closeserial((int)lsock->fd);
4561abb0f93cSkardel 		break;
4562abb0f93cSkardel 
4563abb0f93cSkardel 	default:
4564abb0f93cSkardel 		msyslog(LOG_ERR,
4565abb0f93cSkardel 			"internal error - illegal descriptor type %d - EXITING",
4566abb0f93cSkardel 			(int)lsock->type);
4567abb0f93cSkardel 		exit(1);
4568abb0f93cSkardel 	}
4569abb0f93cSkardel 
4570abb0f93cSkardel 	free(lsock);
4571abb0f93cSkardel 	/*
4572abb0f93cSkardel 	 * remove from activefds
4573abb0f93cSkardel 	 */
4574b3d6264cSchristos 	maintain_activefds(fd, 1);
4575b3d6264cSchristos }
4576abb0f93cSkardel 
4577abb0f93cSkardel 
4578abb0f93cSkardel static void
4579abb0f93cSkardel add_addr_to_list(
4580abb0f93cSkardel 	sockaddr_u *	addr,
458145530cf1Skardel 	endpt *		ep
4582abb0f93cSkardel 	)
4583abb0f93cSkardel {
4584abb0f93cSkardel 	remaddr_t *laddr;
4585abb0f93cSkardel 
4586abb0f93cSkardel #ifdef DEBUG
4587abb0f93cSkardel 	if (find_addr_in_list(addr) == NULL) {
4588abb0f93cSkardel #endif
4589abb0f93cSkardel 		/* not there yet - add to list */
4590abb0f93cSkardel 		laddr = emalloc(sizeof(*laddr));
459145530cf1Skardel 		laddr->addr = *addr;
459245530cf1Skardel 		laddr->ep = ep;
4593abb0f93cSkardel 
4594abb0f93cSkardel 		LINK_SLIST(remoteaddr_list, laddr, link);
4595abb0f93cSkardel 
4596abb0f93cSkardel 		DPRINTF(4, ("Added addr %s to list of addresses\n",
4597abb0f93cSkardel 			    stoa(addr)));
4598abb0f93cSkardel #ifdef DEBUG
4599abb0f93cSkardel 	} else
4600abb0f93cSkardel 		DPRINTF(4, ("WARNING: Attempt to add duplicate addr %s to address list\n",
4601abb0f93cSkardel 			    stoa(addr)));
4602abb0f93cSkardel #endif
4603abb0f93cSkardel }
4604abb0f93cSkardel 
4605abb0f93cSkardel 
4606abb0f93cSkardel static void
4607abb0f93cSkardel delete_addr_from_list(
4608abb0f93cSkardel 	sockaddr_u *addr
4609abb0f93cSkardel 	)
4610abb0f93cSkardel {
4611abb0f93cSkardel 	remaddr_t *unlinked;
4612abb0f93cSkardel 
4613abb0f93cSkardel 	UNLINK_EXPR_SLIST(unlinked, remoteaddr_list, SOCK_EQ(addr,
4614abb0f93cSkardel 		&(UNLINK_EXPR_SLIST_CURRENT()->addr)), link, remaddr_t);
4615abb0f93cSkardel 
4616abb0f93cSkardel 	if (unlinked != NULL) {
4617abb0f93cSkardel 		DPRINTF(4, ("Deleted addr %s from list of addresses\n",
4618abb0f93cSkardel 			stoa(addr)));
4619abb0f93cSkardel 		free(unlinked);
4620abb0f93cSkardel 	}
4621abb0f93cSkardel }
4622abb0f93cSkardel 
4623abb0f93cSkardel 
4624abb0f93cSkardel static void
4625abb0f93cSkardel delete_interface_from_list(
462645530cf1Skardel 	endpt *iface
4627abb0f93cSkardel 	)
4628abb0f93cSkardel {
4629abb0f93cSkardel 	remaddr_t *unlinked;
4630abb0f93cSkardel 
4631ad131110Schristos 	for (;;) {
4632abb0f93cSkardel 		UNLINK_EXPR_SLIST(unlinked, remoteaddr_list, iface ==
463345530cf1Skardel 		    UNLINK_EXPR_SLIST_CURRENT()->ep, link,
4634abb0f93cSkardel 		    remaddr_t);
4635abb0f93cSkardel 
4636ad131110Schristos 		if (unlinked == NULL)
4637ad131110Schristos 			break;
4638abb0f93cSkardel 		DPRINTF(4, ("Deleted addr %s for interface #%d %s from list of addresses\n",
4639abb0f93cSkardel 			    stoa(&unlinked->addr), iface->ifnum,
4640abb0f93cSkardel 			    iface->name));
4641abb0f93cSkardel 		free(unlinked);
4642abb0f93cSkardel 	}
4643abb0f93cSkardel }
4644abb0f93cSkardel 
4645abb0f93cSkardel 
4646abb0f93cSkardel static struct interface *
4647abb0f93cSkardel find_addr_in_list(
4648abb0f93cSkardel 	sockaddr_u *addr
4649abb0f93cSkardel 	)
4650abb0f93cSkardel {
4651abb0f93cSkardel 	remaddr_t *entry;
4652abb0f93cSkardel 
4653abb0f93cSkardel 	DPRINTF(4, ("Searching for addr %s in list of addresses - ",
4654abb0f93cSkardel 		    stoa(addr)));
4655abb0f93cSkardel 
4656abb0f93cSkardel 	for (entry = remoteaddr_list;
4657abb0f93cSkardel 	     entry != NULL;
4658abb0f93cSkardel 	     entry = entry->link)
4659abb0f93cSkardel 		if (SOCK_EQ(&entry->addr, addr)) {
4660abb0f93cSkardel 			DPRINTF(4, ("FOUND\n"));
466145530cf1Skardel 			return entry->ep;
4662abb0f93cSkardel 		}
4663abb0f93cSkardel 
4664abb0f93cSkardel 	DPRINTF(4, ("NOT FOUND\n"));
4665abb0f93cSkardel 	return NULL;
4666abb0f93cSkardel }
4667abb0f93cSkardel 
4668abb0f93cSkardel 
4669abb0f93cSkardel /*
4670abb0f93cSkardel  * Find the given address with the all given flags set in the list
4671abb0f93cSkardel  */
467245530cf1Skardel static endpt *
4673abb0f93cSkardel find_flagged_addr_in_list(
4674abb0f93cSkardel 	sockaddr_u *	addr,
467545530cf1Skardel 	u_int32		flags
4676abb0f93cSkardel 	)
4677abb0f93cSkardel {
4678abb0f93cSkardel 	remaddr_t *entry;
4679abb0f93cSkardel 
4680abb0f93cSkardel 	DPRINTF(4, ("Finding addr %s with flags %d in list: ",
4681abb0f93cSkardel 		    stoa(addr), flags));
4682abb0f93cSkardel 
4683abb0f93cSkardel 	for (entry = remoteaddr_list;
4684abb0f93cSkardel 	     entry != NULL;
4685abb0f93cSkardel 	     entry = entry->link)
4686abb0f93cSkardel 
4687abb0f93cSkardel 		if (SOCK_EQ(&entry->addr, addr)
468845530cf1Skardel 		    && (entry->ep->flags & flags) == flags) {
4689abb0f93cSkardel 
4690abb0f93cSkardel 			DPRINTF(4, ("FOUND\n"));
469145530cf1Skardel 			return entry->ep;
4692abb0f93cSkardel 		}
4693abb0f93cSkardel 
4694abb0f93cSkardel 	DPRINTF(4, ("NOT FOUND\n"));
4695abb0f93cSkardel 	return NULL;
4696abb0f93cSkardel }
4697abb0f93cSkardel 
4698abb0f93cSkardel 
469945530cf1Skardel const char *
470045530cf1Skardel localaddrtoa(
470145530cf1Skardel 	endpt *la
470245530cf1Skardel 	)
470345530cf1Skardel {
470445530cf1Skardel 	return (NULL == la)
470545530cf1Skardel 		   ? "<null>"
470645530cf1Skardel 		   : stoa(&la->sin);
470745530cf1Skardel }
470845530cf1Skardel 
470945530cf1Skardel 
4710abb0f93cSkardel #ifdef HAS_ROUTING_SOCKET
4711abb0f93cSkardel # ifndef UPDATE_GRACE
4712abb0f93cSkardel #  define UPDATE_GRACE	2	/* wait UPDATE_GRACE seconds before scanning */
4713abb0f93cSkardel # endif
4714abb0f93cSkardel 
4715abb0f93cSkardel static void
4716abb0f93cSkardel process_routing_msgs(struct asyncio_reader *reader)
4717abb0f93cSkardel {
4718abb0f93cSkardel 	char buffer[5120];
4719abb0f93cSkardel 	int cnt, msg_type;
4720abb0f93cSkardel #ifdef HAVE_RTNETLINK
4721abb0f93cSkardel 	struct nlmsghdr *nh;
4722abb0f93cSkardel #else
4723b3d6264cSchristos 	struct rt_msghdr rtm;
4724abb0f93cSkardel 	char *p;
4725abb0f93cSkardel #endif
4726abb0f93cSkardel 
4727abb0f93cSkardel 	if (disable_dynamic_updates) {
4728abb0f93cSkardel 		/*
4729abb0f93cSkardel 		 * discard ourselves if we are not needed any more
4730abb0f93cSkardel 		 * usually happens when running unprivileged
4731abb0f93cSkardel 		 */
4732abb0f93cSkardel 		remove_asyncio_reader(reader);
4733abb0f93cSkardel 		delete_asyncio_reader(reader);
4734abb0f93cSkardel 		return;
4735abb0f93cSkardel 	}
4736abb0f93cSkardel 
4737abb0f93cSkardel 	cnt = read(reader->fd, buffer, sizeof(buffer));
4738abb0f93cSkardel 
4739abb0f93cSkardel 	if (cnt < 0) {
474009f14f80Schristos 		if (errno == ENOBUFS) {
4741436bf552Sroy 			msyslog(LOG_DEBUG,
4742436bf552Sroy 				"routing socket overflowed"
4743436bf552Sroy 				" - will update interfaces");
474427c1ab70Sroy 			/*
474527c1ab70Sroy 			 * drain the routing socket as we need to update
474627c1ab70Sroy 			 * the interfaces anyway
474727c1ab70Sroy 			 */
474827c1ab70Sroy 			do {
474927c1ab70Sroy 				cnt = read(reader->fd, buffer, sizeof(buffer));
475027c1ab70Sroy 			} while (cnt != -1 || errno == ENOBUFS);
475127c1ab70Sroy 			timer_interfacetimeout(current_time + UPDATE_GRACE);
4752ee0588e9Sroy 		} else if (errno != EINTR) {
475309f14f80Schristos 			msyslog(LOG_ERR,
475409f14f80Schristos 				"routing socket reports: %m - disabling");
4755abb0f93cSkardel 			remove_asyncio_reader(reader);
4756abb0f93cSkardel 			delete_asyncio_reader(reader);
475709f14f80Schristos 		}
4758abb0f93cSkardel 		return;
4759abb0f93cSkardel 	}
4760abb0f93cSkardel 
4761abb0f93cSkardel 	/*
4762abb0f93cSkardel 	 * process routing message
4763abb0f93cSkardel 	 */
4764abb0f93cSkardel #ifdef HAVE_RTNETLINK
4765bd25f4c4Schristos 	for (nh = UA_PTR(struct nlmsghdr, buffer);
4766abb0f93cSkardel 	     NLMSG_OK(nh, cnt);
4767*e03b00c8Schristos 	     nh = NLMSG_NEXT(nh, cnt))
4768*e03b00c8Schristos 	{
4769abb0f93cSkardel 		msg_type = nh->nlmsg_type;
4770abb0f93cSkardel #else
4771abb0f93cSkardel 	for (p = buffer;
4772abb0f93cSkardel 	     (p + sizeof(struct rt_msghdr)) <= (buffer + cnt);
4773*e03b00c8Schristos 	     p += rtm.rtm_msglen)
4774*e03b00c8Schristos 	{
4775b3d6264cSchristos 		memcpy(&rtm, p, sizeof(rtm));
4776b3d6264cSchristos 		if (rtm.rtm_version != RTM_VERSION) {
4777abb0f93cSkardel 			msyslog(LOG_ERR,
4778abb0f93cSkardel 				"version mismatch (got %d - expected %d) on routing socket - disabling",
4779b3d6264cSchristos 				rtm.rtm_version, RTM_VERSION);
4780abb0f93cSkardel 
4781abb0f93cSkardel 			remove_asyncio_reader(reader);
4782abb0f93cSkardel 			delete_asyncio_reader(reader);
4783abb0f93cSkardel 			return;
4784abb0f93cSkardel 		}
4785b3d6264cSchristos 		msg_type = rtm.rtm_type;
4786abb0f93cSkardel #endif
4787abb0f93cSkardel 		switch (msg_type) {
4788abb0f93cSkardel #ifdef RTM_NEWADDR
4789abb0f93cSkardel 		case RTM_NEWADDR:
4790abb0f93cSkardel #endif
4791abb0f93cSkardel #ifdef RTM_DELADDR
4792abb0f93cSkardel 		case RTM_DELADDR:
4793abb0f93cSkardel #endif
4794abb0f93cSkardel #ifdef RTM_ADD
4795abb0f93cSkardel 		case RTM_ADD:
4796abb0f93cSkardel #endif
4797abb0f93cSkardel #ifdef RTM_DELETE
4798abb0f93cSkardel 		case RTM_DELETE:
4799abb0f93cSkardel #endif
4800abb0f93cSkardel #ifdef RTM_REDIRECT
4801abb0f93cSkardel 		case RTM_REDIRECT:
4802abb0f93cSkardel #endif
4803abb0f93cSkardel #ifdef RTM_CHANGE
4804abb0f93cSkardel 		case RTM_CHANGE:
4805abb0f93cSkardel #endif
4806abb0f93cSkardel #ifdef RTM_IFINFO
4807abb0f93cSkardel 		case RTM_IFINFO:
4808abb0f93cSkardel #endif
4809abb0f93cSkardel #ifdef RTM_NEWLINK
4810abb0f93cSkardel 		case RTM_NEWLINK:
4811abb0f93cSkardel #endif
4812abb0f93cSkardel #ifdef RTM_DELLINK
4813abb0f93cSkardel 		case RTM_DELLINK:
4814abb0f93cSkardel #endif
4815abb0f93cSkardel #ifdef RTM_NEWROUTE
4816abb0f93cSkardel 		case RTM_NEWROUTE:
4817abb0f93cSkardel #endif
4818abb0f93cSkardel #ifdef RTM_DELROUTE
4819abb0f93cSkardel 		case RTM_DELROUTE:
4820abb0f93cSkardel #endif
4821abb0f93cSkardel 			/*
4822abb0f93cSkardel 			 * we are keen on new and deleted addresses and
4823abb0f93cSkardel 			 * if an interface goes up and down or routing
4824abb0f93cSkardel 			 * changes
4825abb0f93cSkardel 			 */
4826abb0f93cSkardel 			DPRINTF(3, ("routing message op = %d: scheduling interface update\n",
4827abb0f93cSkardel 				    msg_type));
4828abb0f93cSkardel 			timer_interfacetimeout(current_time + UPDATE_GRACE);
4829abb0f93cSkardel 			break;
4830abb0f93cSkardel #ifdef HAVE_RTNETLINK
4831abb0f93cSkardel 		case NLMSG_DONE:
4832abb0f93cSkardel 			/* end of multipart message */
4833abb0f93cSkardel 			return;
4834abb0f93cSkardel #endif
4835abb0f93cSkardel 		default:
4836abb0f93cSkardel 			/*
4837abb0f93cSkardel 			 * the rest doesn't bother us.
4838abb0f93cSkardel 			 */
4839abb0f93cSkardel 			DPRINTF(4, ("routing message op = %d: ignored\n",
4840abb0f93cSkardel 				    msg_type));
4841abb0f93cSkardel 			break;
4842abb0f93cSkardel 		}
4843abb0f93cSkardel 	}
4844abb0f93cSkardel }
4845abb0f93cSkardel 
4846abb0f93cSkardel /*
4847abb0f93cSkardel  * set up routing notifications
4848abb0f93cSkardel  */
4849abb0f93cSkardel static void
4850abb0f93cSkardel init_async_notifications()
4851abb0f93cSkardel {
4852abb0f93cSkardel 	struct asyncio_reader *reader;
4853abb0f93cSkardel #ifdef HAVE_RTNETLINK
4854abb0f93cSkardel 	int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
4855abb0f93cSkardel 	struct sockaddr_nl sa;
4856abb0f93cSkardel #else
4857abb0f93cSkardel 	int fd = socket(PF_ROUTE, SOCK_RAW, 0);
485827c1ab70Sroy #ifdef SO_RERROR
485927c1ab70Sroy 	int on = 1;
486027c1ab70Sroy #endif
4861abb0f93cSkardel #endif
4862867deecaSroy #ifdef RO_MSGFILTER
4863867deecaSroy 	unsigned char msgfilter[] = {
4864867deecaSroy #ifdef RTM_NEWADDR
4865867deecaSroy 		RTM_NEWADDR,
4866867deecaSroy #endif
4867867deecaSroy #ifdef RTM_DELADDR
4868867deecaSroy 		RTM_DELADDR,
4869867deecaSroy #endif
4870867deecaSroy #ifdef RTM_ADD
4871867deecaSroy 		RTM_ADD,
4872867deecaSroy #endif
4873867deecaSroy #ifdef RTM_DELETE
4874867deecaSroy 		RTM_DELETE,
4875867deecaSroy #endif
4876867deecaSroy #ifdef RTM_REDIRECT
4877867deecaSroy 		RTM_REDIRECT,
4878867deecaSroy #endif
4879867deecaSroy #ifdef RTM_CHANGE
4880867deecaSroy 		RTM_CHANGE,
4881867deecaSroy #endif
4882867deecaSroy #ifdef RTM_IFINFO
4883867deecaSroy 		RTM_IFINFO,
4884867deecaSroy #endif
4885867deecaSroy #ifdef RTM_NEWLINK
4886867deecaSroy 		RTM_NEWLINK,
4887867deecaSroy #endif
4888867deecaSroy #ifdef RTM_DELLINK
4889867deecaSroy 		RTM_DELLINK,
4890867deecaSroy #endif
4891867deecaSroy #ifdef RTM_NEWROUTE
4892867deecaSroy 		RTM_NEWROUTE,
4893867deecaSroy #endif
4894867deecaSroy #ifdef RTM_DELROUTE
4895867deecaSroy 		RTM_DELROUTE,
4896867deecaSroy #endif
4897867deecaSroy 	};
4898867deecaSroy #endif /* !RO_MSGFILTER */
4899867deecaSroy 
4900abb0f93cSkardel 	if (fd < 0) {
4901abb0f93cSkardel 		msyslog(LOG_ERR,
4902abb0f93cSkardel 			"unable to open routing socket (%m) - using polled interface update");
4903abb0f93cSkardel 		return;
4904abb0f93cSkardel 	}
4905abb0f93cSkardel 
4906abb0f93cSkardel 	fd = move_fd(fd);
4907abb0f93cSkardel #ifdef HAVE_RTNETLINK
4908b3d6264cSchristos 	ZERO(sa);
4909abb0f93cSkardel 	sa.nl_family = PF_NETLINK;
4910abb0f93cSkardel 	sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR
4911abb0f93cSkardel 		       | RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_ROUTE
4912abb0f93cSkardel 		       | RTMGRP_IPV4_MROUTE | RTMGRP_IPV6_ROUTE
4913abb0f93cSkardel 		       | RTMGRP_IPV6_MROUTE;
4914abb0f93cSkardel 	if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
4915abb0f93cSkardel 		msyslog(LOG_ERR,
4916abb0f93cSkardel 			"bind failed on routing socket (%m) - using polled interface update");
4917abb0f93cSkardel 		return;
4918abb0f93cSkardel 	}
4919abb0f93cSkardel #endif
4920867deecaSroy #ifdef RO_MSGFILTER
4921867deecaSroy 	if (setsockopt(fd, PF_ROUTE, RO_MSGFILTER,
4922867deecaSroy 	    &msgfilter, sizeof(msgfilter)) == -1)
4923867deecaSroy 		msyslog(LOG_ERR, "RO_MSGFILTER: %m");
4924867deecaSroy #endif
492527c1ab70Sroy #ifdef SO_RERROR
492627c1ab70Sroy 	if (setsockopt(fd, SOL_SOCKET, SO_RERROR, &on, sizeof(on)) == -1)
492727c1ab70Sroy 		msyslog(LOG_ERR, "SO_RERROR: %m");
492827c1ab70Sroy #endif
4929b3d6264cSchristos 	make_socket_nonblocking(fd);
4930abb0f93cSkardel #if defined(HAVE_SIGNALED_IO)
4931abb0f93cSkardel 	init_socket_sig(fd);
4932abb0f93cSkardel #endif /* HAVE_SIGNALED_IO */
4933abb0f93cSkardel 
4934abb0f93cSkardel 	reader = new_asyncio_reader();
4935abb0f93cSkardel 
4936abb0f93cSkardel 	reader->fd = fd;
4937abb0f93cSkardel 	reader->receiver = process_routing_msgs;
4938abb0f93cSkardel 
4939abb0f93cSkardel 	add_asyncio_reader(reader, FD_TYPE_SOCKET);
4940abb0f93cSkardel 	msyslog(LOG_INFO,
4941abb0f93cSkardel 		"Listening on routing socket on fd #%d for interface updates",
4942abb0f93cSkardel 		fd);
4943abb0f93cSkardel }
4944abb0f93cSkardel #else
4945abb0f93cSkardel /* HAS_ROUTING_SOCKET not defined */
4946abb0f93cSkardel static void
4947abb0f93cSkardel init_async_notifications(void)
4948abb0f93cSkardel {
4949abb0f93cSkardel }
4950abb0f93cSkardel #endif
4951b3d6264cSchristos 
4952