DNS-config.patch   [plain text]


diff -up -upr /SourceCache/ntp/ntp-42.2/ntp/include/ntp.h ./include/ntp.h
--- /SourceCache/ntp/ntp-42.2/ntp/include/ntp.h	2006-12-28 04:03:04.000000000 -0800
+++ ./include/ntp.h	2008-08-17 08:53:02.000000000 -0700
@@ -256,6 +256,11 @@ struct peer {
 	struct sockaddr_storage srcadr; /* address of remote host */
 	struct interface *dstadr; /* pointer to address on local host */
         ISC_LINK(struct peer) ilink; /* interface link list */
+#ifdef __APPLE__
+        char *dns_name;
+        u_long dns_update;
+        u_int dns_ttl;
+#endif /* __APPLE__ */
 	associd_t associd;	/* association ID */
 	u_char	version;	/* version number */
 	u_char	hmode;		/* local association mode */
@@ -434,6 +439,11 @@ struct peer {
 #define FLAG_TRUE	0x2000	/* select truechimer */
 #define	FLAG_PREEMPT	0x4000	/* preemptable association */
 #define	FLAG_DYNAMIC	0x8000	/* dynamic addresses - allow configuration even if no interface is found */
+/* local configuration was specified -- override any DNS configuration */
+#define FLAG_UMINPOLL   0x10000
+#define FLAG_UMAXPOLL   0x20000
+#define FLAG_UBURST	0x40000
+#define FLAG_UIBURST	0x80000
 
 /*
  * Definitions for the clear() routine.  We use memset() to clear
diff -up -upr /SourceCache/ntp/ntp-42.2/ntp/include/ntpd.h ./include/ntpd.h
--- /SourceCache/ntp/ntp-42.2/ntp/include/ntpd.h	2006-12-28 04:03:06.000000000 -0800
+++ ./include/ntpd.h	2008-08-16 23:00:49.000000000 -0700
@@ -140,7 +140,7 @@ extern  void         set_peerdstadr     
 extern	struct peer *newpeer	P((struct sockaddr_storage *, struct interface *, int, int, int, int, u_int, u_char, int, keyid_t));
 extern	void	peer_all_reset	P((void));
 extern	void	peer_clr_stats	P((void));
-extern	struct peer *peer_config P((struct sockaddr_storage *, struct interface *, int, int, int, int, u_int, int, keyid_t, u_char *));
+extern	struct peer *peer_config P((struct sockaddr_storage *, struct interface *, int, int, int, int, u_int, int, keyid_t, u_char *, char *));
 extern	void	peer_reset	P((struct peer *));
 extern	int 	peer_unconfig	P((struct sockaddr_storage *, struct interface *, int));
 extern  void    refresh_all_peerinterfaces P((void));
@@ -151,7 +151,7 @@ extern	void	clear_all	P((void));
 extern	void	expire_all	P((void));
 #endif /* OPENSSL */
 extern	struct	peer *findmanycastpeer	P((struct recvbuf *));
-
+extern	u_long	get_dns_flags	P((char*, struct peer *));
 /* ntp_crypto.c */
 #ifdef OPENSSL
 extern	int	crypto_recv	P((struct peer *, struct recvbuf *));
@@ -440,6 +442,7 @@ extern volatile int alarm_flag;		/* alar
 extern u_char	sys_revoke;		/* keys revoke timeout (log2 s) */
 extern volatile u_long alarm_overflow;
 extern u_long	current_time;		/* current time (s) */
+extern u_long	dns_timer;
 extern u_long	timer_timereset;
 extern u_long	timer_overflows;
 extern u_long	timer_xmtcalls;
diff -up -upr /SourceCache/ntp/ntp-42.2/ntp/ntpd/Makefile.in ./ntpd/Makefile.in
--- /SourceCache/ntp/ntp-42.2/ntp/ntpd/Makefile.in	2007-09-10 17:18:02.000000000 -0700
+++ ./ntpd/Makefile.in	2008-08-16 23:00:49.000000000 -0700
@@ -280,7 +280,7 @@ man_MANS = ntpd.1 ntpdsim.1
 # sqrt                                ntp_control.o
 # floor                               refclock_wwv.o
 # which are (usually) provided by -lm.
-ntpd_LDADD = $(LDADD) -lm @LCRYPTO@ $(LIBOPTS_LDADD) ../libntp/libntp.a
+ntpd_LDADD = $(LDADD) -lm @LCRYPTO@ $(LIBOPTS_LDADD) ../libntp/libntp.a -framework IOKit -lresolv
 ntpdsim_LDADD = $(LDADD) ../libntp/libntpsim.a -lm @LCRYPTO@ $(LIBOPTS_LDADD)
 ntpdsim_CFLAGS = $(CFLAGS) -DSIM
 check_y2k_LDADD = $(LDADD) ../libntp/libntp.a
diff -up -upr /SourceCache/ntp/ntp-42.2/ntp/ntpd/ntp_config.c ./ntpd/ntp_config.c
--- /SourceCache/ntp/ntp-42.2/ntp/ntpd/ntp_config.c	2007-08-18 13:24:43.000000000 -0700
+++ ./ntpd/ntp_config.c	2008-08-16 23:00:49.000000000 -0700
@@ -767,6 +767,8 @@ getconfig(
 						    "minpoll: provided value (%d) is below minimum (%d)",
 						    minpoll, NTP_MINPOLL);
 					minpoll = NTP_MINPOLL;
+				    } else {
+				        peerflags |= FLAG_UMINPOLL;
 				    }
 				    break;
 
@@ -784,6 +786,8 @@ getconfig(
 						    "maxpoll: provided value (%d) is above maximum (%d)",
 						    maxpoll, NTP_MAXPOLL);
 					maxpoll = NTP_MAXPOLL;
+				    } else {
+				        peerflags |= FLAG_UMAXPOLL;
 				    }
 				    break;
 
@@ -803,11 +807,11 @@ getconfig(
 				    peerflags |= FLAG_TRUE;
 
 				case CONF_MOD_BURST:
-				    peerflags |= FLAG_BURST;
+				    peerflags |= FLAG_BURST | FLAG_UBURST;
 				    break;
 
 				case CONF_MOD_IBURST:
-				    peerflags |= FLAG_IBURST;
+				    peerflags |= FLAG_IBURST | FLAG_UIBURST;
 				    break;
 
 			        case CONF_MOD_DYNAMIC:
@@ -859,7 +863,7 @@ getconfig(
 			    if (peer_config(&peeraddr,
 				ANY_INTERFACE_CHOOSE(&peeraddr), hmode,
 				peerversion, minpoll, maxpoll, peerflags,
-				ttl, peerkey, peerkeystr) == 0) {
+				ttl, peerkey, peerkeystr, tokens[1]) == 0) {
 					msyslog(LOG_ERR,
 						"configuration of %s failed",
 						stoa(&peeraddr));
diff -up -upr /SourceCache/ntp/ntp-42.2/ntp/ntpd/ntp_intres.c ./ntpd/ntp_intres.c
--- /SourceCache/ntp/ntp-42.2/ntp/ntpd/ntp_intres.c	2008-05-02 15:12:12.000000000 -0700
+++ ./ntpd/ntp_intres.c	2008-08-16 23:00:49.000000000 -0700
@@ -463,7 +463,10 @@ addentry(
 	ce->ce_flags = (u_char)flags;
 	ce->ce_ttl = (u_char)ttl;
 	ce->ce_keyid = keyid;
-	strncpy((char *)ce->ce_keystr, keystr, MAXFILENAME);
+	if (keyid)
+		strlcpy((char *)ce->ce_keystr, keystr, MAXFILENAME);
+	else
+		strlcpy((char *)ce->ce_keystr, cp, MAXFILENAME);
 	ce->ce_next = NULL;
 
 	if (confentries == NULL) {
diff -up -upr /SourceCache/ntp/ntp-42.2/ntp/ntpd/ntp_peer.c ./ntpd/ntp_peer.c
--- /SourceCache/ntp/ntp-42.2/ntp/ntpd/ntp_peer.c	2007-05-27 04:02:49.000000000 -0700
+++ ./ntpd/ntp_peer.c	2008-08-17 08:49:26.000000000 -0700
@@ -423,12 +423,13 @@ peer_config(
 	u_int flags,
 	int ttl,
 	keyid_t key,
-	u_char *keystr
+	u_char *keystr,
+	char *dns_name
 	)
 {
 	register struct peer *peer;
 	u_char cast_flags;
-
+	u_long next_update;
 	/*
 	 * First search from the beginning for an association with given
 	 * remote address and mode. If an interface is given, search
@@ -520,6 +521,12 @@ peer_config(
 		flags |= FLAG_IBURST;
 	peer = newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll,
 	    flags | FLAG_CONFIG, cast_flags, ttl, key);
+	if (peer) {
+		peer->dns_name = strdup(dns_name);
+		next_update = get_dns_flags(dns_name, peer);
+		if (dns_timer == 0 || (dns_timer > next_update))
+			dns_timer = next_update;
+	}
 	return (peer);
 }
 
@@ -1061,3 +1066,145 @@ findmanycastpeer(
 	}
 	return (NULL);
 }
+
+#include <dns_util.h>
+
+u_long get_dns_flags(
+    char *dns_name,
+    struct peer* peer) 
+{
+	dns_handle_t handle;
+	dns_reply_t *reply;
+	dns_TXT_record_t *txt;
+	uint16_t klass, type;
+
+	handle = dns_open(NULL);
+	if (!handle) {
+	    return 0;
+	}
+	dns_class_number("IN", &klass);
+	dns_type_number("TXT", &type);
+	reply = dns_lookup(handle, dns_name, klass, type);
+
+	if (reply) {
+		int a;
+#if DEBUG
+		if (debug > 1) {
+			dns_print_reply(reply, stdout, 0xffff);
+			printf("status: %d\n", reply->status); /* skip if != DNS_STATUS_OK */
+			printf("answer count: %d\n", reply->header->ancount); /* skip if <= 0 */
+		}
+#endif
+		for (a = 0; a < reply->header->ancount; a++) {
+		        if ((reply->answer[a]->dnstype != type) ||
+			    (reply->answer[a]->dnsclass != klass))
+			    	continue; /* ignore non-TXT */
+			txt = reply->answer[a]->data.TXT;
+			if (txt) {
+				int s;
+				u_int old_flags = peer->flags & (FLAG_BURST | FLAG_IBURST);
+				u_int new_flags = 0;
+				u_char minpoll = NTP_MINDPOLL;
+				u_char maxpoll = NTP_MAXDPOLL;
+				for (s = 0; s < txt->string_count; s++) {
+#if DEBUG
+					if (debug > 1)
+						printf("%d: %s\n", s, txt->strings[s]);
+#endif
+					if (0 == strncmp(txt->strings[s], "ntp ", 4)) {
+						char *next = txt->strings[s]+4;
+						char *arg, *p;
+						long arg_val;
+						if (peer->dns_ttl != reply->answer[a]->ttl) {
+							peer->dns_ttl = reply->answer[a]->ttl;
+							msyslog(LOG_INFO, "DNS %s ttl %d",
+								dns_name, peer->dns_ttl);
+						}
+						if (peer->dns_ttl != 0)
+							peer->dns_update = current_time + peer->dns_ttl;
+						while (NULL != (p = strsep(&next, " \t"))) {
+							switch (*p) {
+							case 'b': /* burst */
+								if (strcmp(p, "burst") == 0) {
+									new_flags |= FLAG_BURST;
+								} else {
+									msyslog(LOG_WARNING, "DNS %s unknown configuration [%s]", dns_name, p);
+								}
+								break;
+
+							case 'i': /* iburst */
+								if (0 == strcmp(p, "iburst")) {
+									new_flags |= FLAG_IBURST;
+								} else { 
+									msyslog(LOG_WARNING, "DNS %s unknown configuration [%s]", dns_name, p);
+								}
+								break;
+
+							case 'm': /* min|maxpoll */
+								if ((0 == (strcmp(p, "minpoll"))) || (0 == strcmp(p, "maxpoll"))) {
+									if (next) {
+										arg = strsep(&next, " \t");
+										arg_val = strtol(arg, NULL, 10);
+										if (p[1] == 'i') {
+											minpoll = (u_char)max(NTP_MINPOLL, arg_val);
+										} else {
+											maxpoll = (u_char)min(NTP_MAXPOLL, arg_val);
+										}
+									} else {
+										msyslog(LOG_WARNING, "DNS %s option %s missing numeric argument", dns_name, p);
+									}
+								} else { 
+									msyslog(LOG_WARNING, "DNS %s unknown configuration [%s]", dns_name, p);
+								}
+								break;
+
+							default: 
+								msyslog(LOG_WARNING, "DNS %s unknown configuration [%s]", dns_name, p);
+								break;
+							}
+						}
+					} /* ignore random txt records */
+				}
+				if (0 == (peer->flags & FLAG_UMINPOLL) && (minpoll != peer->minpoll)) {
+					peer->minpoll = minpoll;
+					msyslog(LOG_INFO, "DNS %s minpoll %d",
+						dns_name, peer->minpoll);
+				}
+				if (0 == (peer->flags & FLAG_UMAXPOLL) && (maxpoll != peer->maxpoll)) {
+					peer->maxpoll = maxpoll;
+					msyslog(LOG_INFO, "DNS %s maxpoll %d",
+						dns_name, peer->maxpoll);
+				}
+				if (new_flags != old_flags) {
+					u_int changes;
+					if (peer->flags & FLAG_UIBURST) /* Don't override config setting */
+						new_flags |= FLAG_IBURST;
+					if (peer->flags & FLAG_IBURST)
+						new_flags |= FLAG_IBURST;
+					changes = new_flags ^ old_flags;
+					if (changes & FLAG_IBURST) {
+						if (new_flags & FLAG_IBURST)
+							peer->flags |= FLAG_IBURST;
+						else
+							peer->flags &= ~FLAG_IBURST;
+						msyslog(LOG_INFO, "DNS %s %ciburst",
+							dns_name,
+							(new_flags & FLAG_IBURST) ? '+' : '-');
+					}
+					if (changes & FLAG_BURST) {
+						if (new_flags & FLAG_BURST)
+							peer->flags |= FLAG_BURST;
+						else
+							peer->flags &= ~FLAG_BURST;
+						msyslog(LOG_INFO, "DNS %s %cburst",
+							dns_name,
+							(new_flags & FLAG_BURST) ? '+' : '-');
+					}
+				}
+			}
+		}
+		dns_free_reply(reply);
+	}
+	dns_free(handle);
+	return peer->dns_update;
+}
diff -up -upr /SourceCache/ntp/ntp-42.2/ntp/ntpd/ntp_request.c ./ntpd/ntp_request.c
--- /SourceCache/ntp/ntp-42.2/ntp/ntpd/ntp_request.c	2006-12-28 04:03:33.000000000 -0800
+++ ./ntpd/ntp_request.c	2008-08-16 23:00:49.000000000 -0700
@@ -1410,7 +1410,7 @@ do_conf(
 		if (peer_config(&peeraddr, (struct interface *)0,
 		    temp_cp.hmode, temp_cp.version, temp_cp.minpoll, 
 		    temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid,
-		    NULL) == 0) {
+		    NULL, temp_cp.keystr) == 0) {
 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
 			return;
 		}
@@ -2671,7 +2671,7 @@ set_clock_fudge(
 	register int items;
 	struct refclockstat clock_stat;
 	struct sockaddr_storage addr;
-	struct sockaddr_in tmp_clock;
+	struct sockaddr_in tmp_clock = { 0 };
 	l_fp ltmp;
 
 	memset((char *)&addr, 0, sizeof addr);
diff -up -upr /SourceCache/ntp/ntp-42.2/ntp/ntpd/ntp_timer.c ./ntpd/ntp_timer.c
--- /SourceCache/ntp/ntp-42.2/ntp/ntpd/ntp_timer.c	2006-12-28 04:03:34.000000000 -0800
+++ ./ntpd/ntp_timer.c	2008-08-16 23:00:49.000000000 -0700
@@ -49,6 +49,7 @@ static	u_long keys_timer;		/* minute tim
 static	u_long stats_timer;		/* stats timer */
 static	u_long huffpuff_timer;		/* huff-n'-puff timer */
 static  u_long interface_timer;	        /* interface update timer */
+u_long dns_timer;		/* update DNS flags on peers */
 #ifdef OPENSSL
 static	u_long revoke_timer;		/* keys revoke timer */
 u_char	sys_revoke = KEY_REVOKE;	/* keys revoke timeout (log2 s) */
@@ -252,6 +253,24 @@ get_timer_handle(void)
 }
 #endif
 
+static u_long update_dns_peers(void)
+{
+	u_int n;
+	u_long next_update = ~0UL, curr_update;
+	struct peer *peer;
+
+	for (n = 0; n < NTP_HASH_SIZE; n++) {
+		for (peer = peer_hash[n]; peer != 0; peer = peer->next) {
+			if (peer->dns_update && peer->dns_update <= current_time) {
+				curr_update = get_dns_flags(peer->dns_name, peer);
+				if (curr_update < next_update)
+					next_update = curr_update;
+			}
+		}
+	}
+	return next_update;
+}
+
 /*
  * timer - dispatch anyone who needs to be
  */
@@ -350,6 +369,10 @@ timer(void)
 #endif
 	  interface_update(NULL, NULL);
 	}
+
+	if (dns_timer && (dns_timer <= current_time)) {
+		dns_timer = update_dns_peers();
+	}
 	
 	/*
 	 * Finally, periodically write stats.