aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Novakovic <chris@chrisn.me.uk>2018-04-23 22:56:39 -0400
committerDavid S. Miller <davem@davemloft.net>2018-04-24 13:40:42 -0400
commitc04d2cb2009f87cba7431c4ed3d85a602f71658e (patch)
tree3a3a99d67bf734d15698d47cdf9940e1bf873d71
parent4d019b3f80dc147fd9d177e7e0337fc66e3c0032 (diff)
ipconfig: Write NTP server IPs to /proc/net/ipconfig/ntp_servers
Distributed filesystems are most effective when the server and client clocks are synchronised. Embedded devices often use NFS for their root filesystem but typically do not contain an RTC, so the clocks of the NFS server and the embedded device will be out-of-sync when the root filesystem is mounted (and may not be synchronised until late in the boot process). Extend ipconfig with the ability to export IP addresses of NTP servers it discovers to /proc/net/ipconfig/ntp_servers. They can be supplied as follows: - If ipconfig is configured manually via the "ip=" or "nfsaddrs=" kernel command line parameters, one NTP server can be specified in the new "<ntp0-ip>" parameter. - If ipconfig is autoconfigured via DHCP, request DHCP option 42 in the DHCPDISCOVER message, and record the IP addresses of up to three NTP servers sent by the responding DHCP server in the subsequent DHCPOFFER message. ipconfig will only write the NTP server IP addresses it discovers to /proc/net/ipconfig/ntp_servers, one per line (in the order received from the DHCP server, if DHCP autoconfiguration is used); making use of these NTP servers is the responsibility of a user space process (e.g. an initrd/initram script that invokes an NTP client before mounting an NFS root filesystem). Signed-off-by: Chris Novakovic <chris@chrisn.me.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/filesystems/nfs/nfsroot.txt35
-rw-r--r--net/ipv4/ipconfig.c118
2 files changed, 136 insertions, 17 deletions
diff --git a/Documentation/filesystems/nfs/nfsroot.txt b/Documentation/filesystems/nfs/nfsroot.txt
index a1030bea60d3..d2963123eb1c 100644
--- a/Documentation/filesystems/nfs/nfsroot.txt
+++ b/Documentation/filesystems/nfs/nfsroot.txt
@@ -5,6 +5,7 @@ Written 1996 by Gero Kuhlmann <gero@gkminix.han.de>
5Updated 1997 by Martin Mares <mj@atrey.karlin.mff.cuni.cz> 5Updated 1997 by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
6Updated 2006 by Nico Schottelius <nico-kernel-nfsroot@schottelius.org> 6Updated 2006 by Nico Schottelius <nico-kernel-nfsroot@schottelius.org>
7Updated 2006 by Horms <horms@verge.net.au> 7Updated 2006 by Horms <horms@verge.net.au>
8Updated 2018 by Chris Novakovic <chris@chrisn.me.uk>
8 9
9 10
10 11
@@ -79,7 +80,7 @@ nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
79 80
80 81
81ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>: 82ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:
82 <dns0-ip>:<dns1-ip> 83 <dns0-ip>:<dns1-ip>:<ntp0-ip>
83 84
84 This parameter tells the kernel how to configure IP addresses of devices 85 This parameter tells the kernel how to configure IP addresses of devices
85 and also how to set up the IP routing table. It was originally called 86 and also how to set up the IP routing table. It was originally called
@@ -178,9 +179,18 @@ ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:
178 <dns1-ip> IP address of secondary nameserver. 179 <dns1-ip> IP address of secondary nameserver.
179 See <dns0-ip>. 180 See <dns0-ip>.
180 181
181 After configuration (whether manual or automatic) is complete, a file is 182 <ntp0-ip> IP address of a Network Time Protocol (NTP) server.
182 created at /proc/net/pnp in the following format; lines are omitted if 183 Value is exported to /proc/net/ipconfig/ntp_servers, but is
183 their respective value is empty following configuration. 184 otherwise unused (see below).
185
186 Default: None if not using autoconfiguration; determined
187 automatically if using autoconfiguration.
188
189 After configuration (whether manual or automatic) is complete, two files
190 are created in the following format; lines are omitted if their respective
191 value is empty following configuration:
192
193 - /proc/net/pnp:
184 194
185 #PROTO: <DHCP|BOOTP|RARP|MANUAL> (depending on configuration method) 195 #PROTO: <DHCP|BOOTP|RARP|MANUAL> (depending on configuration method)
186 domain <dns-domain> (if autoconfigured, the DNS domain) 196 domain <dns-domain> (if autoconfigured, the DNS domain)
@@ -189,13 +199,26 @@ ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:
189 nameserver <dns2-ip> (tertiary name server IP) 199 nameserver <dns2-ip> (tertiary name server IP)
190 bootserver <server-ip> (NFS server IP) 200 bootserver <server-ip> (NFS server IP)
191 201
192 <dns-domain> and <dns2-ip> are requested during autoconfiguration; they 202 - /proc/net/ipconfig/ntp_servers:
193 cannot be specified as part of the "ip=" kernel command line parameter. 203
204 <ntp0-ip> (NTP server IP)
205 <ntp1-ip> (NTP server IP)
206 <ntp2-ip> (NTP server IP)
207
208 <dns-domain> and <dns2-ip> (in /proc/net/pnp) and <ntp1-ip> and <ntp2-ip>
209 (in /proc/net/ipconfig/ntp_servers) are requested during autoconfiguration;
210 they cannot be specified as part of the "ip=" kernel command line parameter.
194 211
195 Because the "domain" and "nameserver" options are recognised by DNS 212 Because the "domain" and "nameserver" options are recognised by DNS
196 resolvers, /etc/resolv.conf is often linked to /proc/net/pnp on systems 213 resolvers, /etc/resolv.conf is often linked to /proc/net/pnp on systems
197 that use an NFS root filesystem. 214 that use an NFS root filesystem.
198 215
216 Note that the kernel will not synchronise the system time with any NTP
217 servers it discovers; this is the responsibility of a user space process
218 (e.g. an initrd/initramfs script that passes the IP addresses listed in
219 /proc/net/ipconfig/ntp_servers to an NTP client before mounting the real
220 root filesystem if it is on NFS).
221
199 222
200nfsrootdebug 223nfsrootdebug
201 224
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 9abf833f3a99..d839d74853fc 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -28,6 +28,9 @@
28 * 28 *
29 * Multiple Nameservers in /proc/net/pnp 29 * Multiple Nameservers in /proc/net/pnp
30 * -- Josef Siemes <jsiemes@web.de>, Aug 2002 30 * -- Josef Siemes <jsiemes@web.de>, Aug 2002
31 *
32 * NTP servers in /proc/net/ipconfig/ntp_servers
33 * -- Chris Novakovic <chris@chrisn.me.uk>, April 2018
31 */ 34 */
32 35
33#include <linux/types.h> 36#include <linux/types.h>
@@ -93,6 +96,7 @@
93#define CONF_TIMEOUT_MAX (HZ*30) /* Maximum allowed timeout */ 96#define CONF_TIMEOUT_MAX (HZ*30) /* Maximum allowed timeout */
94#define CONF_NAMESERVERS_MAX 3 /* Maximum number of nameservers 97#define CONF_NAMESERVERS_MAX 3 /* Maximum number of nameservers
95 - '3' from resolv.h */ 98 - '3' from resolv.h */
99#define CONF_NTP_SERVERS_MAX 3 /* Maximum number of NTP servers */
96 100
97#define NONE cpu_to_be32(INADDR_NONE) 101#define NONE cpu_to_be32(INADDR_NONE)
98#define ANY cpu_to_be32(INADDR_ANY) 102#define ANY cpu_to_be32(INADDR_ANY)
@@ -152,6 +156,7 @@ static int ic_proto_used; /* Protocol used, if any */
152#define ic_proto_used 0 156#define ic_proto_used 0
153#endif 157#endif
154static __be32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */ 158static __be32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */
159static __be32 ic_ntp_servers[CONF_NTP_SERVERS_MAX]; /* NTP server IP addresses */
155static u8 ic_domain[64]; /* DNS (not NIS) domain name */ 160static u8 ic_domain[64]; /* DNS (not NIS) domain name */
156 161
157/* 162/*
@@ -579,6 +584,15 @@ static inline void __init ic_nameservers_predef(void)
579 ic_nameservers[i] = NONE; 584 ic_nameservers[i] = NONE;
580} 585}
581 586
587/* Predefine NTP servers */
588static inline void __init ic_ntp_servers_predef(void)
589{
590 int i;
591
592 for (i = 0; i < CONF_NTP_SERVERS_MAX; i++)
593 ic_ntp_servers[i] = NONE;
594}
595
582/* 596/*
583 * DHCP/BOOTP support. 597 * DHCP/BOOTP support.
584 */ 598 */
@@ -674,6 +688,7 @@ ic_dhcp_init_options(u8 *options, struct ic_device *d)
674 17, /* Boot path */ 688 17, /* Boot path */
675 26, /* MTU */ 689 26, /* MTU */
676 40, /* NIS domain name */ 690 40, /* NIS domain name */
691 42, /* NTP servers */
677 }; 692 };
678 693
679 *e++ = 55; /* Parameter request list */ 694 *e++ = 55; /* Parameter request list */
@@ -753,12 +768,13 @@ static void __init ic_bootp_init_ext(u8 *e)
753 */ 768 */
754static inline void __init ic_bootp_init(void) 769static inline void __init ic_bootp_init(void)
755{ 770{
756 /* Re-initialise all name servers to NONE, in case any were set via the 771 /* Re-initialise all name servers and NTP servers to NONE, in case any
757 * "ip=" or "nfsaddrs=" kernel command line parameters: any IP addresses 772 * were set via the "ip=" or "nfsaddrs=" kernel command line parameters:
758 * specified there will already have been decoded but are no longer 773 * any IP addresses specified there will already have been decoded but
759 * needed 774 * are no longer needed
760 */ 775 */
761 ic_nameservers_predef(); 776 ic_nameservers_predef();
777 ic_ntp_servers_predef();
762 778
763 dev_add_pack(&bootp_packet_type); 779 dev_add_pack(&bootp_packet_type);
764} 780}
@@ -922,6 +938,15 @@ static void __init ic_do_bootp_ext(u8 *ext)
922 ic_bootp_string(utsname()->domainname, ext+1, *ext, 938 ic_bootp_string(utsname()->domainname, ext+1, *ext,
923 __NEW_UTS_LEN); 939 __NEW_UTS_LEN);
924 break; 940 break;
941 case 42: /* NTP servers */
942 servers = *ext / 4;
943 if (servers > CONF_NTP_SERVERS_MAX)
944 servers = CONF_NTP_SERVERS_MAX;
945 for (i = 0; i < servers; i++) {
946 if (ic_ntp_servers[i] == NONE)
947 memcpy(&ic_ntp_servers[i], ext+1+4*i, 4);
948 }
949 break;
925 } 950 }
926} 951}
927 952
@@ -1268,6 +1293,7 @@ static int __init ic_dynamic(void)
1268 1293
1269#ifdef CONFIG_PROC_FS 1294#ifdef CONFIG_PROC_FS
1270 1295
1296/* Name servers: */
1271static int pnp_seq_show(struct seq_file *seq, void *v) 1297static int pnp_seq_show(struct seq_file *seq, void *v)
1272{ 1298{
1273 int i; 1299 int i;
@@ -1306,7 +1332,7 @@ static const struct file_operations pnp_seq_fops = {
1306}; 1332};
1307 1333
1308/* Create the /proc/net/ipconfig directory */ 1334/* Create the /proc/net/ipconfig directory */
1309static int ipconfig_proc_net_init(void) 1335static int __init ipconfig_proc_net_init(void)
1310{ 1336{
1311 ipconfig_dir = proc_net_mkdir(&init_net, "ipconfig", init_net.proc_net); 1337 ipconfig_dir = proc_net_mkdir(&init_net, "ipconfig", init_net.proc_net);
1312 if (!ipconfig_dir) 1338 if (!ipconfig_dir)
@@ -1314,6 +1340,52 @@ static int ipconfig_proc_net_init(void)
1314 1340
1315 return 0; 1341 return 0;
1316} 1342}
1343
1344/* Create a new file under /proc/net/ipconfig */
1345static int ipconfig_proc_net_create(const char *name,
1346 const struct file_operations *fops)
1347{
1348 char *pname;
1349 struct proc_dir_entry *p;
1350
1351 if (!ipconfig_dir)
1352 return -ENOMEM;
1353
1354 pname = kasprintf(GFP_KERNEL, "%s%s", "ipconfig/", name);
1355 if (!pname)
1356 return -ENOMEM;
1357
1358 p = proc_create(pname, 0444, init_net.proc_net, fops);
1359 kfree(pname);
1360 if (!p)
1361 return -ENOMEM;
1362
1363 return 0;
1364}
1365
1366/* Write NTP server IP addresses to /proc/net/ipconfig/ntp_servers */
1367static int ntp_servers_seq_show(struct seq_file *seq, void *v)
1368{
1369 int i;
1370
1371 for (i = 0; i < CONF_NTP_SERVERS_MAX; i++) {
1372 if (ic_ntp_servers[i] != NONE)
1373 seq_printf(seq, "%pI4\n", &ic_ntp_servers[i]);
1374 }
1375 return 0;
1376}
1377
1378static int ntp_servers_seq_open(struct inode *inode, struct file *file)
1379{
1380 return single_open(file, ntp_servers_seq_show, NULL);
1381}
1382
1383static const struct file_operations ntp_servers_seq_fops = {
1384 .open = ntp_servers_seq_open,
1385 .read = seq_read,
1386 .llseek = seq_lseek,
1387 .release = single_release,
1388};
1317#endif /* CONFIG_PROC_FS */ 1389#endif /* CONFIG_PROC_FS */
1318 1390
1319/* 1391/*
@@ -1388,17 +1460,20 @@ static int __init ip_auto_config(void)
1388 int err; 1460 int err;
1389 unsigned int i; 1461 unsigned int i;
1390 1462
1391 /* Initialise all name servers to NONE (but only if the "ip=" or 1463 /* Initialise all name servers and NTP servers to NONE (but only if the
1392 * "nfsaddrs=" kernel command line parameters weren't decoded, otherwise 1464 * "ip=" or "nfsaddrs=" kernel command line parameters weren't decoded,
1393 * we'll overwrite the IP addresses specified there) 1465 * otherwise we'll overwrite the IP addresses specified there)
1394 */ 1466 */
1395 if (ic_set_manually == 0) 1467 if (ic_set_manually == 0) {
1396 ic_nameservers_predef(); 1468 ic_nameservers_predef();
1469 ic_ntp_servers_predef();
1470 }
1397 1471
1398#ifdef CONFIG_PROC_FS 1472#ifdef CONFIG_PROC_FS
1399 proc_create("pnp", 0444, init_net.proc_net, &pnp_seq_fops); 1473 proc_create("pnp", 0444, init_net.proc_net, &pnp_seq_fops);
1400 1474
1401 ipconfig_proc_net_init(); 1475 if (ipconfig_proc_net_init() == 0)
1476 ipconfig_proc_net_create("ntp_servers", &ntp_servers_seq_fops);
1402#endif /* CONFIG_PROC_FS */ 1477#endif /* CONFIG_PROC_FS */
1403 1478
1404 if (!ic_enable) 1479 if (!ic_enable)
@@ -1523,6 +1598,19 @@ static int __init ip_auto_config(void)
1523 if (i + 1 == CONF_NAMESERVERS_MAX) 1598 if (i + 1 == CONF_NAMESERVERS_MAX)
1524 pr_cont("\n"); 1599 pr_cont("\n");
1525 } 1600 }
1601 /* NTP servers (if any): */
1602 for (i = 0; i < CONF_NTP_SERVERS_MAX; i++) {
1603 if (ic_ntp_servers[i] != NONE) {
1604 if (i == 0)
1605 pr_info(" ntpserver%u=%pI4",
1606 i, &ic_ntp_servers[i]);
1607 else
1608 pr_cont(", ntpserver%u=%pI4",
1609 i, &ic_ntp_servers[i]);
1610 }
1611 if (i + 1 == CONF_NTP_SERVERS_MAX)
1612 pr_cont("\n");
1613 }
1526#endif /* !SILENT */ 1614#endif /* !SILENT */
1527 1615
1528 /* 1616 /*
@@ -1620,8 +1708,9 @@ static int __init ip_auto_config_setup(char *addrs)
1620 return 1; 1708 return 1;
1621 } 1709 }
1622 1710
1623 /* Initialise all name servers to NONE */ 1711 /* Initialise all name servers and NTP servers to NONE */
1624 ic_nameservers_predef(); 1712 ic_nameservers_predef();
1713 ic_ntp_servers_predef();
1625 1714
1626 /* Parse string for static IP assignment. */ 1715 /* Parse string for static IP assignment. */
1627 ip = addrs; 1716 ip = addrs;
@@ -1680,6 +1769,13 @@ static int __init ip_auto_config_setup(char *addrs)
1680 ic_nameservers[1] = NONE; 1769 ic_nameservers[1] = NONE;
1681 } 1770 }
1682 break; 1771 break;
1772 case 9:
1773 if (CONF_NTP_SERVERS_MAX >= 1) {
1774 ic_ntp_servers[0] = in_aton(ip);
1775 if (ic_ntp_servers[0] == ANY)
1776 ic_ntp_servers[0] = NONE;
1777 }
1778 break;
1683 } 1779 }
1684 } 1780 }
1685 ip = cp; 1781 ip = cp;