+ register struct mount *mp;
+ register struct mbuf *m;
+ struct socket *so;
+ struct vnode *vp;
+ int error, i;
+
+ /*
+ * Do enough of ifconfig(8) so that the critical net interface can
+ * talk to the server.
+ */
+ if (socreate(nfs_diskless.myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0))
+ panic("nfs ifconf");
+ if (ifioctl(so, SIOCAIFADDR, &nfs_diskless.myif, curproc)) /* XXX */
+ panic("nfs ifconf2");
+ soclose(so);
+
+ /*
+ * If the gateway field is filled in, set it as the default route.
+ */
+ if (nfs_diskless.mygateway.sin_len != 0) {
+ struct sockaddr_in sin;
+ extern struct sockaddr_in icmpmask;
+
+ sin.sin_len = sizeof (struct sockaddr_in);
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = 0; /* default */
+ in_sockmaskof(sin.sin_addr, &icmpmask);
+ if (rtrequest(RTM_ADD, (struct sockaddr *)&sin,
+ (struct sockaddr *)&nfs_diskless.mygateway,
+ (struct sockaddr *)&icmpmask,
+ RTF_UP | RTF_GATEWAY, (struct rtentry **)0))
+ panic("nfs root route");
+ }
+
+ /*
+ * If swapping to an nfs node (indicated by swdevt[0].sw_dev == NODEV):
+ * Create a fake mount point just for the swap vnode so that the
+ * swap file can be on a different server from the rootfs.
+ */
+ if (swdevt[0].sw_dev == NODEV) {
+ mp = (struct mount *)malloc((u_long)sizeof(struct mount),
+ M_MOUNT, M_NOWAIT);
+ if (mp == NULL)
+ panic("nfs root mount");
+ mp->mnt_op = &nfs_vfsops;
+ mp->mnt_flag = 0;
+ mp->mnt_mounth = NULLVP;
+
+ /*
+ * Set up the diskless nfs_args for the swap mount point
+ * and then call mountnfs() to mount it.
+ * Since the swap file is not the root dir of a file system,
+ * hack it to a regular file.
+ */
+ nfs_diskless.swap_args.fh = (nfsv2fh_t *)nfs_diskless.swap_fh;
+ MGET(m, MT_SONAME, M_DONTWAIT);
+ if (m == NULL)
+ panic("nfs root mbuf");
+ bcopy((caddr_t)&nfs_diskless.swap_saddr, mtod(m, caddr_t),
+ nfs_diskless.swap_saddr.sin_len);
+ m->m_len = (int)nfs_diskless.swap_saddr.sin_len;
+ nfsargs_ntoh(&nfs_diskless.swap_args);
+ if (mountnfs(&nfs_diskless.swap_args, mp, m, "/swap",
+ nfs_diskless.swap_hostnam, &vp))
+ panic("nfs swap");
+ vp->v_type = VREG;
+ vp->v_flag = 0;
+ swapdev_vp = vp;
+ VREF(vp);
+ swdevt[0].sw_vp = vp;
+ swdevt[0].sw_nblks = ntohl(nfs_diskless.swap_nblks);
+ }
+
+ /*
+ * Create the rootfs mount point.
+ */
+ mp = (struct mount *)malloc((u_long)sizeof(struct mount),
+ M_MOUNT, M_NOWAIT);
+ if (mp == NULL)
+ panic("nfs root mount2");
+ mp->mnt_op = &nfs_vfsops;
+ mp->mnt_flag = MNT_RDONLY;
+ mp->mnt_mounth = NULLVP;
+
+ /*
+ * Set up the root fs args and call mountnfs() to do the rest.
+ */
+ nfs_diskless.root_args.fh = (nfsv2fh_t *)nfs_diskless.root_fh;
+ MGET(m, MT_SONAME, M_DONTWAIT);
+ if (m == NULL)
+ panic("nfs root mbuf2");
+ bcopy((caddr_t)&nfs_diskless.root_saddr, mtod(m, caddr_t),
+ nfs_diskless.root_saddr.sin_len);
+ m->m_len = (int)nfs_diskless.root_saddr.sin_len;
+ nfsargs_ntoh(&nfs_diskless.root_args);
+ if (mountnfs(&nfs_diskless.root_args, mp, m, "/",
+ nfs_diskless.root_hostnam, &vp))
+ panic("nfs root");
+ if (vfs_lock(mp))
+ panic("nfs root2");
+ rootfs = mp;
+ mp->mnt_next = mp;
+ mp->mnt_prev = mp;
+ mp->mnt_vnodecovered = NULLVP;
+ vfs_unlock(mp);
+ rootvp = vp;
+
+ /*
+ * This is not really an nfs issue, but it is much easier to
+ * set hostname here and then let the "/etc/rc.xxx" files
+ * mount the right /var based upon its preset value.
+ */
+ bcopy(nfs_diskless.my_hostnam, hostname, MAXHOSTNAMELEN);
+ hostname[MAXHOSTNAMELEN - 1] = '\0';
+ for (i = 0; i < MAXHOSTNAMELEN; i++)
+ if (hostname[i] == '\0')
+ break;
+ hostnamelen = i;
+ inittodr((time_t)0); /* There is no time in the nfs fsstat so ?? */
+ return (0);
+}
+
+/*
+ * Convert the integer fields of the nfs_args structure from net byte order
+ * to host byte order. Called by nfs_mountroot() above.
+ */
+void
+nfsargs_ntoh(nfsp)
+ register struct nfs_args *nfsp;
+{
+
+ NTOHL(nfsp->sotype);
+ NTOHL(nfsp->proto);
+ NTOHL(nfsp->flags);
+ NTOHL(nfsp->wsize);
+ NTOHL(nfsp->rsize);
+ NTOHL(nfsp->timeo);
+ NTOHL(nfsp->retrans);
+ NTOHL(nfsp->maxgrouplist);
+ NTOHL(nfsp->readahead);
+ NTOHL(nfsp->leaseterm);
+ NTOHL(nfsp->deadthresh);