From 184c157e2fd77e16817f96eed2020ee887e1c36b Mon Sep 17 00:00:00 2001 From: benno <> Date: Tue, 30 May 2017 23:30:48 +0000 Subject: [PATCH] add option "query from " to ntpd.conf, to specify a local IP address for outgoing ntp queries. From Job Snijders, thanks! with feedback and ok henning@ --- src/usr.sbin/ntpd/client.c | 14 +++++++++++++- src/usr.sbin/ntpd/ntp.c | 4 +++- src/usr.sbin/ntpd/ntpd.conf.5 | 12 ++++++++++-- src/usr.sbin/ntpd/ntpd.h | 6 +++++- src/usr.sbin/ntpd/parse.y | 33 +++++++++++++++++++++++++++++++-- 5 files changed, 62 insertions(+), 7 deletions(-) diff --git a/src/usr.sbin/ntpd/client.c b/src/usr.sbin/ntpd/client.c index ad53f609..3de52685 100644 --- a/src/usr.sbin/ntpd/client.c +++ b/src/usr.sbin/ntpd/client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: client.c,v 1.104 2016/09/03 11:52:06 reyk Exp $ */ +/* $OpenBSD: client.c,v 1.105 2017/05/30 23:30:48 benno Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -137,11 +137,23 @@ client_query(struct ntp_peer *p) if (p->query->fd == -1) { struct sockaddr *sa = (struct sockaddr *)&p->addr->ss; + struct sockaddr *qa4 = (struct sockaddr *)&p->query_addr4; + struct sockaddr *qa6 = (struct sockaddr *)&p->query_addr6; if ((p->query->fd = socket(p->addr->ss.ss_family, SOCK_DGRAM, 0)) == -1) fatal("client_query socket"); + if (p->addr->ss.ss_family == qa4->sa_family) { + if (bind(p->query->fd, qa4, SA_LEN(qa4)) == -1) + fatal("couldn't bind to IPv4 query address: %s", + log_sockaddr(qa4)); + } else if (p->addr->ss.ss_family == qa6->sa_family) { + if (bind(p->query->fd, qa6, SA_LEN(qa6)) == -1) + fatal("couldn't bind to IPv6 query address: %s", + log_sockaddr(qa6)); + } + if (connect(p->query->fd, sa, SA_LEN(sa)) == -1) { if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == EHOSTUNREACH || errno == EADDRNOTAVAIL) { diff --git a/src/usr.sbin/ntpd/ntp.c b/src/usr.sbin/ntpd/ntp.c index 2fbaaf71..f7a6edec 100644 --- a/src/usr.sbin/ntpd/ntp.c +++ b/src/usr.sbin/ntpd/ntp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntp.c,v 1.145 2017/01/20 01:21:18 phessler Exp $ */ +/* $OpenBSD: ntp.c,v 1.146 2017/05/30 23:30:48 benno Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -521,6 +521,8 @@ ntp_dispatch_imsg_dns(void) if (peer->addr_head.pool) { npeer = new_peer(); npeer->weight = peer->weight; + npeer->query_addr4 = peer->query_addr4; + npeer->query_addr6 = peer->query_addr6; h->next = NULL; npeer->addr = h; npeer->addr_head.a = h; diff --git a/src/usr.sbin/ntpd/ntpd.conf.5 b/src/usr.sbin/ntpd/ntpd.conf.5 index 4d2d15c6..963ce27b 100644 --- a/src/usr.sbin/ntpd/ntpd.conf.5 +++ b/src/usr.sbin/ntpd/ntpd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ntpd.conf.5,v 1.34 2016/12/30 10:24:15 jmc Exp $ +.\" $OpenBSD: ntpd.conf.5,v 1.35 2017/05/30 23:30:48 benno Exp $ .\" .\" Copyright (c) 2003, 2004 Henning Brauer .\" @@ -14,7 +14,7 @@ .\" AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT .\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: December 30 2016 $ +.Dd $Mdocdate: May 30 2017 $ .Dt NTPD.CONF 5 .Os .Sh NAME @@ -67,6 +67,14 @@ or listen on 127.0.0.1 listen on ::1 listen on 127.0.0.1 rtable 4 +.It Xo Ic query from Ar address +.Xc +Specify a Local IP address the +.Xr ntpd 8 +daemon should use for outgoing queries. +.Bd -literal -offset indent +query from 192.0.2.1 +query from 2001:db8::1 .Ed .It Xo Ic sensor Ar device .Op Ic correction Ar microseconds diff --git a/src/usr.sbin/ntpd/ntpd.h b/src/usr.sbin/ntpd/ntpd.h index fb9cd871..30ef206b 100644 --- a/src/usr.sbin/ntpd/ntpd.h +++ b/src/usr.sbin/ntpd/ntpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ntpd.h,v 1.134 2017/01/09 14:49:22 reyk Exp $ */ +/* $OpenBSD: ntpd.h,v 1.135 2017/05/30 23:30:48 benno Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -153,6 +153,8 @@ struct ntp_peer { struct ntp_query *query; struct ntp_offset reply[OFFSET_ARRAY_SIZE]; struct ntp_offset update; + struct sockaddr_in query_addr4; + struct sockaddr_in6 query_addr6; enum client_state state; time_t next; time_t deadline; @@ -219,6 +221,8 @@ struct ntpd_conf { TAILQ_HEAD(constraints, constraint) constraints; struct ntp_status status; struct ntp_freq freq; + struct sockaddr_in query_addr4; + struct sockaddr_in6 query_addr6; u_int32_t scale; int debug; int verbose; diff --git a/src/usr.sbin/ntpd/parse.y b/src/usr.sbin/ntpd/parse.y index 8da19a21..af4ad173 100644 --- a/src/usr.sbin/ntpd/parse.y +++ b/src/usr.sbin/ntpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.65 2015/10/31 19:32:18 naddy Exp $ */ +/* $OpenBSD: parse.y,v 1.66 2017/05/30 23:30:48 benno Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer @@ -58,6 +58,8 @@ int lungetc(int); int findeol(void); struct ntpd_conf *conf; +struct sockaddr_in query_addr4; +struct sockaddr_in6 query_addr6; struct opts { int weight; @@ -80,7 +82,7 @@ typedef struct { %} -%token LISTEN ON CONSTRAINT CONSTRAINTS FROM +%token LISTEN ON CONSTRAINT CONSTRAINTS FROM QUERY %token SERVER SERVERS SENSOR CORRECTION RTABLE REFID STRATUM WEIGHT %token ERROR %token STRING @@ -130,6 +132,28 @@ main : LISTEN ON address listen_opts { free($3->name); free($3); } + | QUERY FROM STRING { + struct sockaddr_in sin4; + struct sockaddr_in6 sin6; + + sin4.sin_family = AF_INET; + sin4.sin_len = sizeof(struct sockaddr_in); + sin6.sin6_family = AF_INET6; + sin6.sin6_len = sizeof(struct sockaddr_in6); + + if (inet_pton(AF_INET, $3, &sin4.sin_addr) == 1) + memcpy(&query_addr4, &sin4, sin4.sin_len); + else if (inet_pton(AF_INET6, $3, &sin6.sin6_addr) == 1) + memcpy(&query_addr6, &sin6, sin6.sin6_len); + else { + yyerror("invalid IPv4 or IPv6 address: %s\n", + $3); + free($3); + YYERROR; + } + + free($3); + } | SERVERS address server_opts { struct ntp_peer *p; struct ntp_addr *h, *next; @@ -153,6 +177,8 @@ main : LISTEN ON address listen_opts { p = new_peer(); p->weight = $3.weight; + p->query_addr4 = query_addr4; + p->query_addr6 = query_addr6; p->addr = h; p->addr_head.a = h; p->addr_head.pool = 1; @@ -190,6 +216,8 @@ main : LISTEN ON address listen_opts { } p->weight = $3.weight; + p->query_addr4 = query_addr4; + p->query_addr6 = query_addr6; p->addr_head.a = p->addr; p->addr_head.pool = 0; p->addr_head.name = strdup($2->name); @@ -461,6 +489,7 @@ lookup(char *s) { "from", FROM}, { "listen", LISTEN}, { "on", ON}, + { "query", QUERY}, { "refid", REFID}, { "rtable", RTABLE}, { "sensor", SENSOR},