Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > e8c0b673ea1b7e162bcac8e349d03cea > files > 17

ntp-4.2.2p1-15.el5_7.1.src.rpm

diff -up ntp-4.2.2p1/html/ntpd.html.listen ntp-4.2.2p1/html/ntpd.html
--- ntp-4.2.2p1/html/ntpd.html.listen	2011-03-28 14:19:02.854051653 +0200
+++ ntp-4.2.2p1/html/ntpd.html	2011-03-28 16:48:42.676513083 +0200
@@ -34,7 +34,7 @@
 		</ul>
 		<hr>
 		<h4 id="synop">Synopsis</h4>
-		<tt>ntpd [ -46aAbdDgLnNqx ] [ -c <i>conffile</i> ] [ -f <i>driftfile</i> ] [ -i <i>jaildir</i> ] [ -k <i>keyfile</i> ] [ -l <i>logfile</i> ] [ -p <i>pidfile</i> ] [ -P <i>priority</i> ] [ -r <i>broadcastdelay</i> ] [ -s <i>statsdir</i> ] [ -t <i>key</i> ] [ -u <i>user</i>[:<i>group</i>] ] [ -v <i>variable</i> ] [ -V <i>variable</i> ]</tt>
+		<tt>ntpd [ -46aAbdDgLnNqx ] [ -c <i>conffile</i> ] [ -f <i>driftfile</i> ] [ -i <i>jaildir</i> ] [ -I <i>iface</i> ] [ -k <i>keyfile</i> ] [ -l <i>logfile</i> ] [ -p <i>pidfile</i> ] [ -P <i>priority</i> ] [ -r <i>broadcastdelay</i> ] [ -s <i>statsdir</i> ] [ -t <i>key</i> ] [ -u <i>user</i>[:<i>group</i>] ] [ -v <i>variable</i> ] [ -V <i>variable</i> ]</tt>
 		<h4 id="descr">Description</h4>
 		<p>The <tt>ntpd</tt> program is an operating system daemon which sets and maintains the system time of day in synchronism with Internet standard time servers. It is a complete implementation of the Network Time Protocol (NTP) version 4, but also retains compatibility with version 3, as defined by RFC-1305, and version 1 and 2, as defined by RFC-1059 and RFC-1119, respectively. <tt>ntpd</tt> does most computations in 64-bit floating point arithmetic and does relatively clumsy 64-bit fixed point operations only when necessary to preserve the ultimate precision, about 232 picoseconds. While the ultimate precision is not achievable with ordinary workstations and networks of today, it may be required with future gigahertz CPU clocks and gigabit LANs.</p>
 		<h4 id="op">How NTP Operates</h4>
@@ -88,6 +88,8 @@
 			<dd>Normally, <tt>ntpd</tt> exits with a message to the system log if the offset exceeds the panic threshold, which is 1000 s by default. This option allows the time to be set to any value without restriction; however, this can happen only once. If the threshold is exceeded after that, <tt>ntpd</tt> will exit with a message to the system log. This option can be used with the <tt>-q</tt> and <tt>-x</tt> options. See the <tt>tinker</tt> command for other options.
 			<dt><tt>-i <i>jaildir</i></tt>
 			<dd>Chroot the server to the directory <i>jaildir</i>. This option also implies that the server attempts to drop root privileges at startup (otherwise, chroot gives very little additional security), and it is only available if the OS supports to run the server without full root privileges. You may need to also specify a <tt>-u</tt> option.
+			<dt><tt>-I <i>iface</i></tt>
+			<dd>Listen on interface. This option may appear an unlimited number of times.
 			<dt><tt>-k <i>keyfile</i></tt>
 			<dd>Specify the name and path of the symmetric key file. This is the same operation as the <tt>keys <i>keyfile</i></tt> configuration command.
 			<dt><tt>-l <i>logfile</i></tt>
diff -up ntp-4.2.2p1/include/ntpd.h.listen ntp-4.2.2p1/include/ntpd.h
--- ntp-4.2.2p1/include/ntpd.h.listen	2006-06-06 22:16:20.000000000 +0200
+++ ntp-4.2.2p1/include/ntpd.h	2011-03-25 15:55:03.848848253 +0100
@@ -73,6 +73,8 @@ extern  void	enable_broadcast P((struct 
 extern  void	enable_multicast_if P((struct interface *, struct sockaddr_storage *));
 extern	void	interface_dump	 P((struct interface *));
 
+extern	void	add_specific_interface P((const char *));
+extern	void	init_specific_interface P((void));
 extern	void	init_io 	P((void));
 extern	void	input_handler	P((l_fp *));
 extern	void	io_clr_stats	P((void));
diff -up ntp-4.2.2p1/ntpd/cmd_args.c.listen ntp-4.2.2p1/ntpd/cmd_args.c
--- ntp-4.2.2p1/ntpd/cmd_args.c.listen	2011-03-25 15:55:03.772863453 +0100
+++ ntp-4.2.2p1/ntpd/cmd_args.c	2011-03-25 15:55:03.848848253 +0100
@@ -19,9 +19,8 @@
 extern char const *progname;
 extern int default_ai_family;
 int	listen_to_virtual_ips = 1;
-char 	*specific_interface = NULL;        /* interface name or IP address to bind to */
 
-static const char *ntp_options = "46aAbB:c:C:dD:f:gHi:k:l:L:nNO:p:P:qr:s:S:t:T:W:u:v:V:xY:Z:-:";
+static const char *ntp_options = "46aAbB:c:C:dD:f:gHi:I:k:l:L:nNO:p:P:qr:s:S:t:T:W:u:v:V:xY:Z:-:";
 
 #ifdef HAVE_NETINFO
 extern int	check_netinfo;
@@ -34,7 +33,7 @@ void ntpd_usage( void )
 		(void) fprintf(stderr, "\t\t[ -f drift_file ] [ -k key_file ] [ -l log_file ]\n");
 		(void) fprintf(stderr, "\t\t[ -p pid_file ] [ -r broadcast_delay ] [ -s stats_dir ]\n");
 		(void) fprintf(stderr, "\t\t[ -t trusted_key ] [ -v sys_var ] [ -V default_sysvar ]\n");
-		(void) fprintf(stderr, "\t\t[ -L [ interface ] ]\n");
+		(void) fprintf(stderr, "\t\t[ -L [ interface ] ] [ -I interface ]\n");
 #if defined(HAVE_SCHED_SETSCHEDULER)
 		(void) fprintf(stderr, "\t\t[ -P fixed_process_priority ]\n");
 #endif
@@ -77,6 +76,8 @@ getstartup(
 	errflg = 0;
 	progname = argv[0];
 
+	init_specific_interface();
+
 	/*
 	 * Decode argument list
 	 */
@@ -98,11 +99,16 @@ getstartup(
 		    ++errflg;
 		    break;
 #endif
+		case 'I':
+		    add_specific_interface(ntp_optarg);
+		    break;
+
 		case 'L':
 		    listen_to_virtual_ips = 0;
 		    if(ntp_optarg)
-			specific_interface = ntp_optarg; 
+			    add_specific_interface(ntp_optarg);
 		    break;
+
 		case 'l':
 			{
 				FILE *new_file;
@@ -276,7 +282,12 @@ getCmdOpts(
 			getauthkeys(ntp_optarg);
 			break;
 
+		    case 'I':   /* already done at pre-scan */
+			break;
+
 		    case 'L':   /* already done at pre-scan */
+			break;
+
 		    case 'l':   /* already done at pre-scan */
 			break;
 
diff -up ntp-4.2.2p1/ntpd/ntp_io.c.listen ntp-4.2.2p1/ntpd/ntp_io.c
--- ntp-4.2.2p1/ntpd/ntp_io.c.listen	2011-03-25 15:55:03.833851254 +0100
+++ ntp-4.2.2p1/ntpd/ntp_io.c	2011-03-25 15:58:20.072595654 +0100
@@ -53,7 +53,14 @@
 #endif  /* IPv6 Support */
 
 extern int listen_to_virtual_ips;
-extern const char *specific_interface;
+
+/* interface names to listen on */
+struct specific_interface {
+	const char *name;
+	ISC_LINK(struct specific_interface) link;
+};
+
+ISC_LIST(struct specific_interface) specific_interface_list;
 
 #if defined(SYS_WINNT)
 #include <transmitbuff.h>
@@ -203,8 +210,14 @@ int	create_wildcards	P((u_short));
 isc_boolean_t address_okay	P((isc_interface_t *));
 void	convert_isc_if		P((isc_interface_t *, struct interface *, u_short));
 int	findlocalinterface	P((struct sockaddr_storage *));
+int	findclosestinterface	P((struct sockaddr_storage *));
 int	findlocalcastinterface	P((struct sockaddr_storage *, int));
 
+static void		calc_addr_distance(struct sockaddr_storage *,
+					   struct sockaddr_storage *,
+					   struct sockaddr_storage *);
+static int		cmp_addr_distance(struct sockaddr_storage *,
+					  struct sockaddr_storage *);
 /*
  * Routines to read the ntp packets
  */
@@ -577,11 +590,12 @@ address_okay(isc_interface_t *isc_if) {
 	/*
 	 * Check if the interface is specified
 	 */
-	if (specific_interface != NULL) {
-		if (strcasecmp(isc_if->name, specific_interface) == 0)
-			return (ISC_TRUE);
-		else
-			return (ISC_FALSE);
+	if (ISC_LIST_HEAD(specific_interface_list)) {
+		struct specific_interface *iface;
+		for (iface = ISC_LIST_HEAD(specific_interface_list); iface != NULL; iface = ISC_LIST_NEXT(iface, link))
+			if (strcasecmp(isc_if->name, iface->name) == 0)
+				return (ISC_TRUE);
+		return (ISC_FALSE);
 	}
 	else {
 		if (listen_to_virtual_ips == 0  && 
@@ -598,6 +612,24 @@ address_okay(isc_interface_t *isc_if) {
 */
 	return (ISC_TRUE);
 }
+
+void
+add_specific_interface (const char *if_name)
+{
+	struct specific_interface *iface;
+
+	iface = (struct specific_interface *)emalloc(sizeof(struct specific_interface));
+	iface->name = if_name;
+	ISC_LINK_INIT(iface, link);
+	ISC_LIST_APPEND(specific_interface_list, iface, link);
+}
+
+void
+init_specific_interface (void)
+{
+	ISC_LIST_INIT(specific_interface_list);
+}
+
 void
 convert_isc_if(isc_interface_t *isc_if, struct interface *itf, u_short port) {
 
@@ -2649,12 +2681,160 @@ findlocalinterface(
 			break;
 		}
 	}
-	if (idx != -1)
+
+	/* 
+	 * if we didn't find an exact match on saddr, find the closest
+	 * available local address.  This handles the case of the
+	 * address suggested by the kernel being excluded by the user's
+	 * -I and -L options to ntpd.
+	 * See http://bugs.ntp.org/1184 and http://bugs.ntp.org/1683
+	 * for more background.
+	 */
+	if (idx == -1 && (ISC_LIST_HEAD(specific_interface_list) || !listen_to_virtual_ips))
 	{
-		return (idx);
+		idx = findclosestinterface(&saddr);
+	}
+
+	return (idx);
+}
+
+/*
+ * findclosestinterface
+ *
+ * If there are -I/--interface or -L/novirtualips command-line options,
+ * findlocalinterface() may
+ * find the kernel's preferred local address for a given peer address is
+ * administratively unavailable to ntpd, and punt to this routine's more
+ * expensive search.
+ *
+ * Find the numerically closest local address to the one connect()
+ * suggested.  This matches an address on the same subnet first, as
+ * needed by Bug 1184, and provides a consistent choice if there are
+ * multiple feasible local addresses, regardless of the order ntpd
+ * enumerated them.
+ */
+int
+findclosestinterface(
+	struct sockaddr_storage *	addr
+	)
+{
+	int i, winner;
+	struct sockaddr_storage	addr_dist;
+	struct sockaddr_storage	min_dist;
+
+	winner = -1;
+	
+	for (i = nwilds; i < ninterfaces; i++) {
+		if (inter_list[i].ignore_packets ||
+		    addr->ss_family != inter_list[i].family ||
+		    inter_list[i].flags & INT_LOOPBACK)
+			continue;
+		
+		calc_addr_distance(&addr_dist, addr, &inter_list[i].sin);
+		if (-1 == winner ||
+		    -1 == cmp_addr_distance(&addr_dist, &min_dist)) {
+			min_dist = addr_dist;
+			winner = i;
+		}
+	}
+
+	return winner;
+}
+
+
+/*
+ * calc_addr_distance - calculate the distance between two addresses,
+ *			the absolute value of the difference between
+ *			the addresses numerically, stored as an address.
+ */
+
+#define AF(psau)                ((psau)->ss_family)
+#define IS_IPV4(psau)           (AF_INET == AF(psau))
+#define IS_IPV6(psau)           (AF_INET6 == AF(psau))
+#define SOCK_ADDR6(psau)        (((struct sockaddr_in6 *)(psau))->sin6_addr)
+#define NSRCADR6(psau)          (SOCK_ADDR6(psau).s6_addr)
+#define SET_ADDR4(psau, addr4)  (NSRCADR(psau) = htonl(addr4))
+
+static void
+calc_addr_distance(
+	struct sockaddr_storage *		dist,
+	struct sockaddr_storage *	a1,
+	struct sockaddr_storage *	a2
+	)
+{
+	u_int32	a1val;
+	u_int32	a2val;
+	u_int32	v4dist;
+	int	found_greater;
+	int	a1_greater;
+	int	i;
+
+	memset(dist, 0, sizeof(*dist));
+	AF(dist) = AF(a1);
+
+	/* v4 can be done a bit simpler */
+	if (IS_IPV4(a1)) {
+		a1val = SRCADR(a1);
+		a2val = SRCADR(a2);
+		v4dist = (a1val > a2val)
+			     ? a1val - a2val
+			     : a2val - a1val;
+		SET_ADDR4(dist, v4dist);
+
+		return;
 	}
 
-	return (-1);
+	found_greater = FALSE;
+	a1_greater = FALSE;	/* suppress pot. uninit. warning */
+	for (i = 0; i < sizeof(NSRCADR6(a1)); i++) {
+		if (!found_greater &&
+		    NSRCADR6(a1)[i] != NSRCADR6(a2)[i]) {
+			found_greater = TRUE;
+			a1_greater = (NSRCADR6(a1)[i] > NSRCADR6(a2)[i]);
+		}
+		if (!found_greater) {
+			NSRCADR6(dist)[i] = 0;
+		} else {
+			if (a1_greater)
+				NSRCADR6(dist)[i] = NSRCADR6(a1)[i] -
+						    NSRCADR6(a2)[i];
+			else
+				NSRCADR6(dist)[i] = NSRCADR6(a2)[i] -
+						    NSRCADR6(a1)[i];
+		}
+	}
+}
+
+
+/*
+ * cmp_addr_distance - compare two address distances, returning -1, 0,
+ *		       1 to indicate their relationship.
+ */
+static int
+cmp_addr_distance(
+	struct sockaddr_storage *	d1,
+	struct sockaddr_storage *	d2
+	)
+{
+	int	i;
+
+	if (IS_IPV4(d1)) {
+		if (SRCADR(d1) < SRCADR(d2))
+			return -1;
+		else if (SRCADR(d1) == SRCADR(d2))
+			return 0;
+		else
+			return 1;
+	}
+
+	for (i = 0; i < sizeof(NSRCADR6(d1)); i++) {
+		if (NSRCADR6(d1)[i] < NSRCADR6(d2)[i])
+			return -1;
+		else if (NSRCADR6(d1)[i] > NSRCADR6(d2)[i])
+			return 1;
+	}
+
+	return 0;
 }
 
 /*