summaryrefslogtreecommitdiffstats
path: root/usr/kinit/nfsroot.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/kinit/nfsroot.c')
-rw-r--r--usr/kinit/nfsroot.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/usr/kinit/nfsroot.c b/usr/kinit/nfsroot.c
new file mode 100644
index 0000000..3b80773
--- /dev/null
+++ b/usr/kinit/nfsroot.c
@@ -0,0 +1,111 @@
+#include <arpa/inet.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "kinit.h"
+#include "netdev.h"
+#include "nfsmount.h"
+
+static char *sub_client(__u32 client, char *path, size_t len)
+{
+ struct in_addr addr = { client };
+ char buf[len];
+
+ if (strstr(path, "%s") != NULL) {
+ if (client == INADDR_NONE) {
+ fprintf(stderr, "Root-NFS: no client address\n");
+ exit(1);
+ }
+
+ snprintf(buf, len, path, inet_ntoa(addr));
+ strcpy(path, buf);
+ }
+
+ return path;
+}
+
+#define NFS_ARGC 6
+#define MOUNT_POINT "/root"
+
+int mount_nfs_root(int argc, char *argv[], int flags)
+{
+ (void)flags; /* FIXME - don't ignore this */
+
+ struct in_addr addr = { INADDR_NONE };
+ __u32 client = INADDR_NONE;
+ const int len = 1024;
+ struct netdev *dev;
+ char *mtpt = MOUNT_POINT;
+ char *path = NULL;
+ char *dev_bootpath = NULL;
+ char root[len];
+ char *x, *opts;
+ int ret = 0;
+ int a = 1;
+ char *nfs_argv[NFS_ARGC + 1] = { "NFS-Mount" };
+
+ for (dev = ifaces; dev; dev = dev->next) {
+ if (dev->ip_server != INADDR_NONE &&
+ dev->ip_server != INADDR_ANY) {
+ addr.s_addr = dev->ip_server;
+ client = dev->ip_addr;
+ dev_bootpath = dev->bootpath;
+ break;
+ }
+ if (dev->ip_addr != INADDR_NONE && dev->ip_addr != INADDR_ANY)
+ client = dev->ip_addr;
+ }
+
+ /*
+ * if the "nfsroot" option is set then it overrides
+ * bootpath supplied by the boot server.
+ */
+ if ((path = get_arg(argc, argv, "nfsroot=")) == NULL) {
+ if ((path = dev_bootpath) == NULL || path[0] == '\0')
+ /* no path - set a default */
+ path = (char *)"/tftpboot/%s";
+ } else if (dev_bootpath && dev_bootpath[0] != '\0')
+ fprintf(stderr,
+ "nfsroot=%s overrides boot server bootpath %s\n",
+ path, dev_bootpath);
+
+ if ((opts = strchr(path, ',')) != NULL) {
+ *opts++ = '\0';
+ nfs_argv[a++] = (char *)"-o";
+ nfs_argv[a++] = opts;
+ }
+
+ if ((x = strchr(path, ':')) == NULL) {
+ if (addr.s_addr == INADDR_NONE) {
+ fprintf(stderr, "Root-NFS: no server defined\n");
+ exit(1);
+ }
+
+ snprintf(root, len, "%s:%s", inet_ntoa(addr), path);
+ } else {
+ strcpy(root, path);
+ }
+
+ nfs_argv[a++] = sub_client(client, root, len);
+
+ dprintf("NFS-Root: mounting %s on %s with options \"%s\"\n",
+ nfs_argv[a-1], mtpt, opts ? opts : "");
+
+ nfs_argv[a++] = mtpt;
+ nfs_argv[a] = NULL;
+ assert(a <= NFS_ARGC);
+
+ dump_args(a, nfs_argv);
+
+ if ((ret = nfsmount_main(a, nfs_argv)) != 0) {
+ ret = -1;
+ goto done;
+ }
+
+done:
+ return ret;
+}