patch-2.1.34 linux/fs/nfs/nfsroot.c
Next file: linux/fs/nfs/read.c
Previous file: linux/fs/nfs/nfs2xdr.c
Back to the patch index
Back to the overall index
- Lines: 986
- Date:
Mon Apr 14 09:31:09 1997
- Orig file:
v2.1.33/linux/fs/nfs/nfsroot.c
- Orig date:
Mon Apr 7 11:35:31 1997
diff -u --recursive --new-file v2.1.33/linux/fs/nfs/nfsroot.c linux/fs/nfs/nfsroot.c
@@ -51,6 +51,9 @@
* without giving a path name. Fix BOOTP request
* for domainname (domainname is NIS domain, not
* DNS domain!). Skip dummy devices for BOOTP.
+ * Jacek Zapala : Fixed a bug which prevented server-ip address
+ * from nfsroot parameter from being used.
+ * Olaf Kirch : Adapted to new NFS code.
*
*/
@@ -81,8 +84,10 @@
#include <net/ax25.h> /* For AX25_P_IP */
#endif
#include <linux/skbuff.h>
+#include <linux/ip.h>
#include <linux/socket.h>
#include <linux/route.h>
+#include <linux/sunrpc/clnt.h>
#include <linux/nfs.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_mount.h>
@@ -91,11 +96,13 @@
#include <net/sock.h>
#include <asm/segment.h>
+#include <asm/uaccess.h>
+#define NFSDBG_FACILITY NFSDBG_ROOT
/* Range of privileged ports */
-#define STARTPORT 600
-#define ENDPORT 1023
-#define NPORTS (ENDPORT - STARTPORT + 1)
+#define STARTPORT 600
+#define ENDPORT 1023
+#define NPORTS (ENDPORT - STARTPORT + 1)
/* Define the timeout for waiting for a RARP/BOOTP reply */
@@ -119,10 +126,10 @@
/* IP configuration */
static struct device *root_dev = NULL; /* Device selected for booting */
static char user_dev_name[IFNAMSIZ]; /* Name of user-selected boot device */
-static struct sockaddr_in myaddr; /* My IP address */
-static struct sockaddr_in server; /* Server IP address */
-static struct sockaddr_in gateway; /* Gateway IP address */
-static struct sockaddr_in netmask; /* Netmask for local subnet */
+static __u32 myaddr; /* My IP address */
+static __u32 servaddr; /* Server IP address */
+static __u32 gateway; /* Gateway IP address */
+static __u32 netmask; /* Netmask for local subnet */
/* BOOTP/RARP variables */
@@ -130,7 +137,7 @@
static int rarp_flag; /* User said: Use RARP! */
static int bootp_dev_count = 0; /* Number of devices allowing BOOTP */
static int rarp_dev_count = 0; /* Number of devices allowing RARP */
-static struct sockaddr_in rarp_serv; /* IP address of RARP server */
+static __u32 rarp_serv; /* IP address of RARP server */
#if defined(CONFIG_RNFS_BOOTP) || defined(CONFIG_RNFS_RARP)
#define CONFIG_RNFS_DYNAMIC /* Enable dynamic IP config */
@@ -143,8 +150,9 @@
/* NFS-related data */
static struct nfs_mount_data nfs_data; /* NFS mount info */
-static char nfs_path[NFS_MAXPATHLEN] = ""; /* Name of directory to mount */
-static int nfs_port; /* Port to connect to for NFS */
+static char nfs_path[NFS_MAXPATHLEN]; /* Name of directory to mount */
+static int nfs_port; /* Port to connect to for NFS */
+static int mount_port; /* Mount daemon port number */
/* Yes, we use sys_socket, but there's no include file for it */
@@ -193,9 +201,7 @@
bootp_dev_count++;
if (!(dev->flags & IFF_NOARP))
rarp_dev_count++;
-#ifdef NFSROOT_DEBUG
- printk(KERN_NOTICE "Root-NFS: Opened %s\n", dev->name);
-#endif
+ dprintk("Root-NFS: Opened %s\n", dev->name);
}
}
*last = NULL;
@@ -207,6 +213,58 @@
return 0;
}
+static inline void
+set_sockaddr(struct sockaddr_in *sin, __u32 addr, __u16 port)
+{
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = addr;
+ sin->sin_port = port;
+}
+
+static int
+root_dev_chg_route(int op, struct device *dev, __u32 dest, __u32 mask, __u32 gw)
+{
+ struct rtentry route;
+ unsigned long oldfs;
+ int err;
+
+ route.rt_dev = dev->name;
+ route.rt_mtu = dev->mtu;
+ route.rt_flags = RTF_UP;
+ set_sockaddr((struct sockaddr_in *) &route.rt_dst, dest & mask, 0);
+ set_sockaddr((struct sockaddr_in *) &route.rt_genmask, mask, 0);
+
+ if (gw != 0) {
+ set_sockaddr((struct sockaddr_in *) &route.rt_gateway, gw, 0);
+ route.rt_flags |= RTF_GATEWAY;
+ if ((gw ^ myaddr) & netmask) {
+ printk(KERN_ERR "Root-NFS: Gateway not on local network!\n");
+ return -ENETUNREACH;
+ }
+ }
+
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ err = ip_rt_ioctl(op, &route);
+ set_fs(oldfs);
+ printk(KERN_NOTICE "%s route %s %s %s: res %d\n",
+ (op == SIOCADDRT? "add" : "del"),
+ in_ntoa(dest), in_ntoa(mask), in_ntoa(gw), err);
+
+ return err;
+}
+
+static int
+root_dev_add_route(struct device *dev, __u32 dest, __u32 mask, __u32 gateway)
+{
+ return root_dev_chg_route(SIOCADDRT, dev, dest, mask, gateway);
+}
+
+static int
+root_dev_del_route(struct device *dev, __u32 dest, __u32 mask, __u32 gateway)
+{
+ return root_dev_chg_route(SIOCDELRT, dev, dest, mask, gateway);
+}
/*
* Restore the state of all devices. However, keep the root device open
@@ -290,7 +348,7 @@
unsigned long sip, tip;
unsigned char *sha, *tha; /* s for "source", t for "target" */
- /* If this test doesn't pass, its not IP, or we should ignore it anyway */
+ /* If this test doesn't pass, it's not IP, or we should ignore it anyway */
if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd)) {
kfree_skb(skb, FREE_READ);
return 0;
@@ -328,8 +386,8 @@
}
/* Discard packets which are not from specified server. */
if (rarp_flag && !bootp_flag &&
- rarp_serv.sin_addr.s_addr != INADDR_NONE &&
- rarp_serv.sin_addr.s_addr != sip) {
+ rarp_serv != INADDR_NONE &&
+ rarp_serv != sip) {
kfree_skb(skb, FREE_READ);
return 0;
}
@@ -348,14 +406,10 @@
sti();
root_dev = dev;
- if (myaddr.sin_addr.s_addr == INADDR_NONE) {
- myaddr.sin_family = dev->family;
- myaddr.sin_addr.s_addr = tip;
- }
- if (server.sin_addr.s_addr == INADDR_NONE) {
- server.sin_family = dev->family;
- server.sin_addr.s_addr = sip;
- }
+ if (myaddr == INADDR_NONE)
+ myaddr = tip;
+ if (servaddr == INADDR_NONE)
+ servaddr = sip;
kfree_skb(skb, FREE_READ);
return 0;
}
@@ -393,10 +447,8 @@
static struct device *bootp_dev = NULL; /* Device selected as best BOOTP target */
-static int bootp_xmit_fd = -1; /* Socket descriptor for transmit */
-static struct socket *bootp_xmit_sock; /* The socket itself */
-static int bootp_recv_fd = -1; /* Socket descriptor for receive */
-static struct socket *bootp_recv_sock; /* The socket itself */
+static struct socket *bootp_xmit_sock; /* BOOTP send socket */
+static struct socket *bootp_recv_sock; /* BOOTP receive socket */
struct bootp_pkt { /* BOOTP packet format */
u8 op; /* 1=request, 2=reply */
@@ -460,18 +512,8 @@
*/
static int root_add_bootp_route(void)
{
- struct rtentry route;
-
- memset(&route, 0, sizeof(route));
- route.rt_dev = bootp_dev->name;
- route.rt_mss = bootp_dev->mtu;
- route.rt_flags = RTF_UP;
- ((struct sockaddr_in *) &(route.rt_dst)) -> sin_addr.s_addr = 0;
- ((struct sockaddr_in *) &(route.rt_dst)) -> sin_family = AF_INET;
- ((struct sockaddr_in *) &(route.rt_genmask)) -> sin_addr.s_addr = 0;
- ((struct sockaddr_in *) &(route.rt_genmask)) -> sin_family = AF_INET;
- if (ip_rt_new(&route)) {
- printk(KERN_ERR "BOOTP: Adding of route failed!\n");
+ if (root_dev_add_route(bootp_dev, 0, 0, 0) < 0) {
+ printk(KERN_ERR "BOOTP: Failed to add route\n");
return -1;
}
bootp_have_route = 1;
@@ -484,14 +526,7 @@
*/
static int root_del_bootp_route(void)
{
- struct rtentry route;
-
- if (!bootp_have_route)
- return 0;
- memset(&route, 0, sizeof(route));
- ((struct sockaddr_in *) &(route.rt_dst)) -> sin_addr.s_addr = 0;
- ((struct sockaddr_in *) &(route.rt_genmask)) -> sin_addr.s_addr = 0;
- if (ip_rt_kill(&route)) {
+ if (bootp_have_route && root_dev_del_route(bootp_dev, 0, 0, 0) < 0) {
printk(KERN_ERR "BOOTP: Deleting of route failed!\n");
return -1;
}
@@ -503,21 +538,13 @@
/*
* Open UDP socket.
*/
-static int root_open_udp_sock(int *fd, struct socket **sock)
+static int root_open_udp_sock(struct socket **sock)
{
- struct file *file;
- struct inode *inode;
+ int err;
- *fd = sys_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (*fd >= 0) {
- file = current->files->fd[*fd];
- inode = file->f_inode;
- *sock = &inode->u.socket_i;
- return 0;
- }
-
- printk(KERN_ERR "BOOTP: Cannot open UDP socket!\n");
- return -1;
+ if ((err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, sock)) < 0)
+ printk(KERN_ERR "BOOTP: Cannot open UDP socket!\n");
+ return err;
}
@@ -529,9 +556,7 @@
struct sockaddr_in sa;
int result;
- sa.sin_family = AF_INET;
- sa.sin_addr.s_addr = htonl(addr);
- sa.sin_port = htons(port);
+ set_sockaddr(&sa, htonl(addr), htonl(port));
result = sock->ops->connect(sock, (struct sockaddr *) &sa, sizeof(sa), 0);
if (result < 0) {
printk(KERN_ERR "BOOTP: connect() failed\n");
@@ -549,9 +574,7 @@
struct sockaddr_in sa;
int result;
- sa.sin_family = AF_INET;
- sa.sin_addr.s_addr = htonl(addr);
- sa.sin_port = htons(port);
+ set_sockaddr(&sa, htonl(addr), htonl(port));
result = sock->ops->bind(sock, (struct sockaddr *) &sa, sizeof(sa));
if (result < 0) {
printk(KERN_ERR "BOOTP: bind() failed\n");
@@ -575,12 +598,12 @@
set_fs(get_ds());
iov.iov_base = buf;
iov.iov_len = size;
- msg.msg_name = NULL;
+ memset(&msg, 0, sizeof(msg));
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
- msg.msg_accrights = NULL;
- result = sock->ops->sendmsg(sock, &msg, size, 0, 0);
+ result = sock_sendmsg(sock, &msg, size);
set_fs(oldfs);
+
return (result != size);
}
@@ -599,12 +622,11 @@
set_fs(get_ds());
iov.iov_base = buf;
iov.iov_len = size;
- msg.msg_name = NULL;
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_flags = MSG_DONTWAIT;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
- msg.msg_accrights = NULL;
- msg.msg_namelen = 0;
- result = sock->ops->recvmsg(sock, &msg, size, O_NONBLOCK, 0, &msg.msg_namelen);
+ result = sock_recvmsg(sock, &msg, size, MSG_DONTWAIT);
set_fs(oldfs);
return result;
}
@@ -643,10 +665,10 @@
*/
static void root_bootp_close(void)
{
- if (bootp_xmit_fd != -1)
- sys_close(bootp_xmit_fd);
- if (bootp_recv_fd != -1)
- sys_close(bootp_recv_fd);
+ if (bootp_xmit_sock)
+ sock_release(bootp_xmit_sock);
+ if (bootp_recv_sock)
+ sock_release(bootp_recv_sock);
root_del_bootp_route();
root_free_bootp();
}
@@ -695,6 +717,7 @@
xmit_bootp->hlen = best_dev->addr_len;
memcpy(xmit_bootp->hw_addr, best_dev->dev_addr, best_dev->addr_len);
root_bootp_init_ext(xmit_bootp->vendor_area);
+
#ifdef NFSROOT_BOOTP_DEBUG
{
int x;
@@ -714,14 +737,14 @@
return -1;
/* Open the sockets */
- if (root_open_udp_sock(&bootp_xmit_fd, &bootp_xmit_sock) ||
- root_open_udp_sock(&bootp_recv_fd, &bootp_recv_sock))
+ if (root_open_udp_sock(&bootp_xmit_sock) ||
+ root_open_udp_sock(&bootp_recv_sock))
return -1;
/* Bind/connect the sockets */
- ((struct sock *) bootp_xmit_sock->data) -> broadcast = 1;
- ((struct sock *) bootp_xmit_sock->data) -> reuse = 1;
- ((struct sock *) bootp_recv_sock->data) -> reuse = 1;
+ bootp_xmit_sock->sk->broadcast = 1;
+ bootp_xmit_sock->sk->reuse = 1;
+ bootp_recv_sock->sk->reuse = 1;
if (root_bind_udp_sock(bootp_recv_sock, INADDR_ANY, 68) ||
root_bind_udp_sock(bootp_xmit_sock, INADDR_ANY, 68) ||
root_connect_udp_sock(bootp_xmit_sock, INADDR_BROADCAST, 67))
@@ -761,9 +784,9 @@
*/
static void root_do_bootp_ext(u8 *ext)
{
+#ifdef NFSROOT_BOOTP_DEBUG
u8 *c;
-#ifdef NFSROOT_BOOTP_DEBUG
printk("BOOTP: Got extension %02x",*ext);
for(c=ext+2; c<ext+2+ext[1]; c++)
printk(" %02x", *c);
@@ -772,12 +795,12 @@
switch (*ext++) {
case 1: /* Subnet mask */
- if (netmask.sin_addr.s_addr == INADDR_NONE)
- memcpy(&netmask.sin_addr.s_addr, ext+1, 4);
+ if (netmask == INADDR_NONE)
+ memcpy(&netmask, ext+1, 4);
break;
case 3: /* Default gateway */
- if (gateway.sin_addr.s_addr == INADDR_NONE)
- memcpy(&gateway.sin_addr.s_addr, ext+1, 4);
+ if (gateway == INADDR_NONE)
+ memcpy(&gateway, ext+1, 4);
break;
case 12: /* Host name */
root_bootp_string(system_utsname.nodename, ext+1, *ext, __NEW_UTS_LEN);
@@ -810,9 +833,7 @@
recv_bootp->htype != xmit_bootp->htype ||
recv_bootp->hlen != xmit_bootp->hlen ||
recv_bootp->xid != xmit_bootp->xid) {
-#ifdef NFSROOT_BOOTP_DEBUG
- printk("?");
-#endif
+ dprintk("?");
return;
}
@@ -827,9 +848,9 @@
root_dev = bootp_dev;
/* Extract basic fields */
- myaddr.sin_addr.s_addr = recv_bootp->your_ip;
- if (server.sin_addr.s_addr==INADDR_NONE)
- server.sin_addr.s_addr = recv_bootp->server_ip;
+ myaddr = recv_bootp->your_ip;
+ if (servaddr==INADDR_NONE)
+ servaddr = recv_bootp->server_ip;
/* Parse extensions */
if (recv_bootp->vendor_area[0] == 99 && /* Check magic cookie */
@@ -983,14 +1004,28 @@
printk(" OK\n");
printk(KERN_NOTICE "Root-NFS: Got %s answer from %s, ",
(pkt_arrived == ARRIVED_BOOTP) ? "BOOTP" : "RARP",
- in_ntoa(server.sin_addr.s_addr));
- printk("my address is %s\n", in_ntoa(myaddr.sin_addr.s_addr));
+ in_ntoa(servaddr));
+ printk("my address is %s\n", in_ntoa(myaddr));
return 0;
}
#endif
-
+/* Get default netmask - used to be exported from net/ipv4 */
+static unsigned long
+ip_get_mask(unsigned long addr)
+{
+ if (!addr)
+ return 0;
+ addr = ntohl(addr);
+ if (IN_CLASSA(addr))
+ return htonl(IN_CLASSA_NET);
+ if (IN_CLASSB(addr))
+ return htonl(IN_CLASSB_NET);
+ if (IN_CLASSC(addr))
+ return htonl(IN_CLASSC_NET);
+ return 0;
+}
/***************************************************************************
@@ -1060,22 +1095,24 @@
break;
if (*cp == '.' || octets == 3)
octets++;
+ if (octets < 4)
+ cp++;
cq = cp;
}
if (octets == 4 && (*cp == ':' || *cp == '\0')) {
if (*cp == ':')
*cp++ = '\0';
- server.sin_addr.s_addr = in_aton(name);
+ servaddr = in_aton(name);
name = cp;
}
/* Clear the nfs_data structure and setup the server hostname */
memset(&nfs_data, 0, sizeof(nfs_data));
- strncpy(nfs_data.hostname, in_ntoa(server.sin_addr.s_addr),
+ strncpy(nfs_data.hostname, in_ntoa(servaddr),
sizeof(nfs_data.hostname)-1);
/* Set the name of the directory to mount */
- if (nfs_path[0] == '\0' || !strncmp(name, "default", 7))
+ if (nfs_path[0] == '\0' || strncmp(name, "default", 7))
strncpy(buf, name, NFS_MAXPATHLEN);
else
strncpy(buf, nfs_path, NFS_MAXPATHLEN);
@@ -1083,7 +1120,7 @@
*options++ = '\0';
if (!strcmp(buf, "default"))
strcpy(buf, NFS_ROOT);
- cp = in_ntoa(myaddr.sin_addr.s_addr);
+ cp = in_ntoa(myaddr);
if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) {
printk(KERN_ERR "Root-NFS: Pathname for remote directory too long.\n");
return -1;
@@ -1094,10 +1131,11 @@
/* Set some default values */
nfs_port = -1;
- nfs_data.version = NFS_MOUNT_VERSION;
- nfs_data.flags = 0;
+ nfs_data.version = NFS_MNT_VERSION;
+ nfs_data.flags = NFS_MOUNT_NONLM; /* No lockd in nfs root yet */
nfs_data.rsize = NFS_DEF_FILE_IO_BUFFER_SIZE;
nfs_data.wsize = NFS_DEF_FILE_IO_BUFFER_SIZE;
+ nfs_data.bsize = 0;
nfs_data.timeo = 7;
nfs_data.retrans = 3;
nfs_data.acregmin = 3;
@@ -1135,17 +1173,17 @@
/*
* Tell the user what's going on.
*/
-#ifdef NFSROOT_DEBUG
+#ifdef NFSROOT_BOOTP
static void root_nfs_print(void)
{
#define IN_NTOA(x) (((x) == INADDR_NONE) ? "none" : in_ntoa(x))
printk(KERN_NOTICE "Root-NFS: IP config: dev=%s, ",
root_dev ? root_dev->name : "none");
- printk("local=%s, ", IN_NTOA(myaddr.sin_addr.s_addr));
- printk("server=%s, ", IN_NTOA(server.sin_addr.s_addr));
- printk("gw=%s, ", IN_NTOA(gateway.sin_addr.s_addr));
- printk("mask=%s, ", IN_NTOA(netmask.sin_addr.s_addr));
+ printk("local=%s, ", IN_NTOA(myaddr));
+ printk("server=%s, ", IN_NTOA(servaddr));
+ printk("gw=%s, ", IN_NTOA(gateway));
+ printk("mask=%s, ", IN_NTOA(netmask));
printk("host=%s, domain=%s\n",
system_utsname.nodename[0] ? system_utsname.nodename : "none",
system_utsname.domainname[0] ? system_utsname.domainname : "none");
@@ -1189,10 +1227,7 @@
int num = 0;
/* Clear all addresses and strings */
- myaddr.sin_family = server.sin_family = rarp_serv.sin_family =
- gateway.sin_family = netmask.sin_family = AF_INET;
- myaddr.sin_addr.s_addr = server.sin_addr.s_addr = rarp_serv.sin_addr.s_addr =
- gateway.sin_addr.s_addr = netmask.sin_addr.s_addr = INADDR_NONE;
+ myaddr = servaddr = rarp_serv = gateway = netmask = INADDR_NONE;
system_utsname.nodename[0] = '\0';
system_utsname.domainname[0] = '\0';
user_dev_name[0] = '\0';
@@ -1215,26 +1250,24 @@
if ((cp = strchr(ip, ':')))
*cp++ = '\0';
if (strlen(ip) > 0) {
-#ifdef NFSROOT_DEBUG
- printk(KERN_NOTICE "Root-NFS: Config string num %d is \"%s\"\n",
+ dprintk("Root-NFS: Config string num %d is \"%s\"\n",
num, ip);
-#endif
switch (num) {
case 0:
- if ((myaddr.sin_addr.s_addr = in_aton(ip)) == INADDR_ANY)
- myaddr.sin_addr.s_addr = INADDR_NONE;
+ if ((myaddr = in_aton(ip)) == INADDR_ANY)
+ myaddr = INADDR_NONE;
break;
case 1:
- if ((server.sin_addr.s_addr = in_aton(ip)) == INADDR_ANY)
- server.sin_addr.s_addr = INADDR_NONE;
+ if ((servaddr = in_aton(ip)) == INADDR_ANY)
+ servaddr = INADDR_NONE;
break;
case 2:
- if ((gateway.sin_addr.s_addr = in_aton(ip)) == INADDR_ANY)
- gateway.sin_addr.s_addr = INADDR_NONE;
+ if ((gateway = in_aton(ip)) == INADDR_ANY)
+ gateway = INADDR_NONE;
break;
case 3:
- if ((netmask.sin_addr.s_addr = in_aton(ip)) == INADDR_ANY)
- netmask.sin_addr.s_addr = INADDR_NONE;
+ if ((netmask = in_aton(ip)) == INADDR_ANY)
+ netmask = INADDR_NONE;
break;
case 4:
if ((dp = strchr(ip, '.'))) {
@@ -1264,7 +1297,7 @@
ip = cp;
num++;
}
- rarp_serv = server;
+ rarp_serv = servaddr;
}
@@ -1273,22 +1306,20 @@
*/
static int root_nfs_setup(void)
{
- struct rtentry route;
-
/* Set the default system name in case none was previously found */
if (!system_utsname.nodename[0]) {
- strncpy(system_utsname.nodename, in_ntoa(myaddr.sin_addr.s_addr), __NEW_UTS_LEN);
+ strncpy(system_utsname.nodename, in_ntoa(myaddr), __NEW_UTS_LEN);
system_utsname.nodename[__NEW_UTS_LEN] = '\0';
}
/* Set the correct netmask */
- if (netmask.sin_addr.s_addr == INADDR_NONE)
- netmask.sin_addr.s_addr = ip_get_mask(myaddr.sin_addr.s_addr);
+ if (netmask == INADDR_NONE)
+ netmask = ip_get_mask(myaddr);
/* Setup the device correctly */
- root_dev->family = myaddr.sin_family;
- root_dev->pa_addr = myaddr.sin_addr.s_addr;
- root_dev->pa_mask = netmask.sin_addr.s_addr;
+ root_dev->family = AF_INET;
+ root_dev->pa_addr = myaddr;
+ root_dev->pa_mask = netmask;
root_dev->pa_brdaddr = root_dev->pa_addr | ~root_dev->pa_mask;
root_dev->pa_dstaddr = 0;
@@ -1300,32 +1331,18 @@
* gatewayed default route. Note that this gives sufficient network
* setup even for full system operation in all common cases.
*/
- memset(&route, 0, sizeof(route)); /* Local subnet route */
- route.rt_dev = root_dev->name;
- route.rt_mss = root_dev->mtu;
- route.rt_flags = RTF_UP;
- *((struct sockaddr_in *) &(route.rt_dst)) = myaddr;
- (((struct sockaddr_in *) &(route.rt_dst)))->sin_addr.s_addr &= netmask.sin_addr.s_addr;
- *((struct sockaddr_in *) &(route.rt_genmask)) = netmask;
- if (ip_rt_new(&route)) {
+ if (root_dev_add_route(root_dev, myaddr, netmask, 0))
+ {
printk(KERN_ERR "Root-NFS: Adding of local route failed!\n");
return -1;
}
- if (gateway.sin_addr.s_addr != INADDR_NONE) { /* Default route */
- (((struct sockaddr_in *) &(route.rt_dst)))->sin_addr.s_addr = INADDR_ANY;
- (((struct sockaddr_in *) &(route.rt_genmask)))->sin_addr.s_addr = INADDR_ANY;
- *((struct sockaddr_in *) &(route.rt_gateway)) = gateway;
- route.rt_flags |= RTF_GATEWAY;
- if ((gateway.sin_addr.s_addr ^ myaddr.sin_addr.s_addr) & netmask.sin_addr.s_addr) {
- printk(KERN_ERR "Root-NFS: Gateway not on local network!\n");
- return -1;
- }
- if (ip_rt_new(&route)) {
+ if (gateway != INADDR_NONE) { /* Default route */
+ if (root_dev_add_route(root_dev, INADDR_ANY, INADDR_ANY, gateway)) {
printk(KERN_ERR "Root-NFS: Adding of default route failed!\n");
return -1;
}
- } else if ((server.sin_addr.s_addr ^ myaddr.sin_addr.s_addr) & netmask.sin_addr.s_addr) {
+ } else if ((servaddr ^ myaddr) & netmask) {
printk(KERN_ERR "Root-NFS: Boot server not on local network and no default gateway configured!\n");
return -1;
}
@@ -1340,6 +1357,10 @@
*/
int nfs_root_init(char *nfsname, char *nfsaddrs)
{
+#ifdef NFSROOT_DEBUG
+ nfs_debug |= NFSDBG_ROOT;
+#endif
+
/*
* Decode IP addresses and other configuration info contained
* in the nfsaddrs string (which came from the kernel command
@@ -1365,8 +1386,8 @@
* in the (diskless) system and if the server is on another subnet.
* If only one interface is installed, the routing is obvious.
*/
- if ((myaddr.sin_addr.s_addr == INADDR_NONE ||
- server.sin_addr.s_addr == INADDR_NONE ||
+ if ((myaddr == INADDR_NONE ||
+ servaddr == INADDR_NONE ||
(open_base != NULL && open_base->next != NULL))
#ifdef CONFIG_RNFS_DYNAMIC
&& root_auto_config() < 0
@@ -1420,206 +1441,50 @@
Routines to actually mount the root directory
***************************************************************************/
-
-static struct file *nfs_file; /* File descriptor pointing to inode */
-static struct inode *nfs_sock_inode; /* Inode containing socket */
-static int *rpc_packet = NULL; /* RPC packet */
-
-
-/*
- * Open a UDP socket.
- */
-static int root_nfs_open(void)
-{
- /* Open the socket */
- if ((nfs_data.fd = sys_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
- printk(KERN_ERR "Root-NFS: Cannot open UDP socket for NFS!\n");
- return -1;
- }
- nfs_file = current->files->fd[nfs_data.fd];
- nfs_sock_inode = nfs_file->f_inode;
- return 0;
-}
-
-
-/*
- * Close the UDP file descriptor. If nfs_read_super is successful, it
- * increases the reference count, so we can simply close the file, and
- * the socket keeps open.
- */
-static void root_nfs_close(void)
-{
- /*
- * The following close doesn't touch the server structure, which
- * now contains a file pointer pointing into nowhere. The system
- * _should_ crash as soon as someone tries to select on the root
- * filesystem. Haven't tried it yet - we can still change it back
- * to the old way of keeping a static copy of all important data
- * structures, including their pointers. At least this should be
- * checked out _carefully_ before going into a public release
- * kernel. - GK
- */
- sys_close(nfs_data.fd);
-}
-
-
-/*
- * Find a suitable listening port and bind to it
- */
-static int root_nfs_bind(void)
-{
- int res = -1;
- short port = STARTPORT;
- struct sockaddr_in *sin = &myaddr;
- int i;
-
- if (nfs_sock_inode->u.socket_i.ops->bind) {
- for (i = 0; i < NPORTS && res < 0; i++) {
- sin->sin_port = htons(port++);
- if (port > ENDPORT) {
- port = STARTPORT;
- }
- res = nfs_sock_inode->u.socket_i.ops->bind(&nfs_sock_inode->u.socket_i,
- (struct sockaddr *)sin,
- sizeof(struct sockaddr_in));
- }
- }
- if (res < 0) {
- printk(KERN_ERR "Root-NFS: Cannot find a suitable listening port\n");
- root_nfs_close();
- return -1;
- }
-#ifdef NFSROOT_DEBUG
- printk(KERN_NOTICE "Root-NFS: Binding to listening port %d\n", port);
-#endif
- return 0;
-}
-
-
-/*
- * Send an RPC request and wait for the answer
- */
-static int *root_nfs_call(int *end)
-{
- struct socket *sock;
- int dummylen;
- static struct nfs_server s = {
- 0, /* struct file * */
- 0, /* struct rsock * */
- {
- 0, "",
- }, /* toaddr */
- 0, /* lock */
- NULL, /* wait queue */
- NFS_MOUNT_SOFT, /* flags */
- 0, 0, /* rsize, wsize */
- 0, /* timeo */
- 0, /* retrans */
- 3 * HZ, 60 * HZ, 30 * HZ, 60 * HZ, "\0"
- };
-
- s.file = nfs_file;
- sock = &((nfs_file->f_inode)->u.socket_i);
-
- /* Extract the other end of the socket into s->toaddr */
- sock->ops->getname(sock, &(s.toaddr), &dummylen, 1);
- ((struct sockaddr_in *) &s.toaddr)->sin_port = server.sin_port;
- ((struct sockaddr_in *) &s.toaddr)->sin_family = server.sin_family;
- ((struct sockaddr_in *) &s.toaddr)->sin_addr.s_addr = server.sin_addr.s_addr;
-
- s.rsock = rpc_makesock(nfs_file);
- s.flags = nfs_data.flags;
- s.rsize = nfs_data.rsize;
- s.wsize = nfs_data.wsize;
- s.timeo = nfs_data.timeo * HZ / 10;
- s.retrans = nfs_data.retrans;
- strcpy(s.hostname, nfs_data.hostname);
-
- /*
- * First connect the UDP socket to a server port, then send the
- * packet out, and finally check whether the answer is OK.
- */
- if (nfs_sock_inode->u.socket_i.ops->connect &&
- nfs_sock_inode->u.socket_i.ops->connect(&nfs_sock_inode->u.socket_i,
- (struct sockaddr *) &server,
- sizeof(struct sockaddr_in),
- nfs_file->f_flags) < 0)
- return NULL;
- if (nfs_rpc_call(&s, rpc_packet, end, nfs_data.wsize) < 0)
- return NULL;
- return rpc_verify(rpc_packet);
-}
-
-
-/*
- * Create an RPC packet header
- */
-static int *root_nfs_header(int proc, int program, int version)
-{
- int groups[] = { 0, NOGROUP };
-
- if (rpc_packet == NULL) {
- if (!(rpc_packet = kmalloc(nfs_data.wsize + 1024, GFP_NFS))) {
- printk(KERN_ERR "Root-NFS: Cannot allocate UDP buffer\n");
- return NULL;
- }
- }
- return rpc_header(rpc_packet, proc, program, version, 0, 0, groups);
-}
-
-
/*
* Query server portmapper for the port of a daemon program
*/
-static int root_nfs_get_port(int program, int version)
+static int root_nfs_getport(int program, int version)
{
- int *p;
-
- /* Prepare header for portmap request */
- server.sin_port = htons(NFS_PMAP_PORT);
- p = root_nfs_header(NFS_PMAP_PROC, NFS_PMAP_PROGRAM, NFS_PMAP_VERSION);
- if (!p)
- return -1;
+ struct sockaddr_in sin;
- /* Set arguments for portmapper */
- *p++ = htonl(program);
- *p++ = htonl(version);
- *p++ = htonl(IPPROTO_UDP);
- *p++ = 0;
-
- /* Send request to server portmapper */
- if ((p = root_nfs_call(p)) == NULL)
- return -1;
-
- return ntohl(*p);
+printk(KERN_NOTICE "Looking up port of RPC %d/%d on %s\n",
+ program, version, in_ntoa(servaddr));
+ set_sockaddr(&sin, servaddr, 0);
+ return rpc_getport_external(&sin, program, version, IPPROTO_UDP);
}
/*
* Get portnumbers for mountd and nfsd from server
+ * The RPC layer does support portmapper queries; the only reason to
+ * keep this code is that we may want to use fallback ports. But is there
+ * actually someone who does not run portmap?
*/
static int root_nfs_ports(void)
{
- int port;
+ int port;
if (nfs_port < 0) {
- if ((port = root_nfs_get_port(NFS_NFS_PROGRAM, NFS_NFS_VERSION)) < 0) {
- printk(KERN_ERR "Root-NFS: Unable to get nfsd port number from server, using default\n");
- port = NFS_NFS_PORT;
+ if ((port = root_nfs_getport(NFS_PROGRAM, NFS_VERSION)) < 0) {
+ printk(KERN_ERR "Root-NFS: Unable to get nfsd port "
+ "number from server, using default\n");
+ port = NFS_PORT;
}
nfs_port = port;
-#ifdef NFSROOT_DEBUG
- printk(KERN_NOTICE "Root-NFS: Portmapper on server returned %d as nfsd port\n", port);
-#endif
+ dprintk("Root-NFS: Portmapper on server returned %d "
+ "as nfsd port\n", port);
}
- if ((port = root_nfs_get_port(NFS_MOUNT_PROGRAM, NFS_MOUNT_VERSION)) < 0) {
- printk(KERN_ERR "Root-NFS: Unable to get mountd port number from server, using default\n");
- port = NFS_MOUNT_PORT;
+
+ if ((port = root_nfs_getport(NFS_MNT_PROGRAM, NFS_MNT_VERSION)) < 0) {
+ printk(KERN_ERR "Root-NFS: Unable to get mountd port "
+ "number from server, using default\n");
+ port = NFS_MNT_PORT;
}
- server.sin_port = htons(port);
-#ifdef NFSROOT_DEBUG
- printk(KERN_NOTICE "Root-NFS: Portmapper on server returned %d as mountd port\n", port);
-#endif
+
+ mount_port = htons(port);
+ dprintk("Root-NFS: Portmapper on server returned %d "
+ "as mountd port\n", port);
return 0;
}
@@ -1631,40 +1496,16 @@
*/
static int root_nfs_get_handle(void)
{
- int len, status, *p;
-
- /* Prepare header for mountd request */
- p = root_nfs_header(NFS_MOUNT_PROC, NFS_MOUNT_PROGRAM, NFS_MOUNT_VERSION);
- if (!p) {
- root_nfs_close();
- return -1;
- }
+ struct sockaddr_in sin;
+ int status;
- /* Set arguments for mountd */
- len = strlen(nfs_path);
- *p++ = htonl(len);
- memcpy(p, nfs_path, len);
- len = (len + 3) >> 2;
- p[len] = 0;
- p += len;
-
- /* Send request to server mountd */
- if ((p = root_nfs_call(p)) == NULL) {
- root_nfs_close();
- return -1;
- }
- status = ntohl(*p++);
- if (status == 0) {
- nfs_data.root = *((struct nfs_fh *) p);
- printk(KERN_NOTICE "Root-NFS: Got file handle for %s via RPC\n", nfs_path);
- } else {
- printk(KERN_ERR "Root-NFS: Server returned error %d while mounting %s\n",
- status, nfs_path);
- root_nfs_close();
- return -1;
- }
+ set_sockaddr(&sin, servaddr, mount_port);
+ status = nfs_mount(&sin, nfs_path, &nfs_data.root);
+ if (status < 0)
+ printk(KERN_ERR "Root-NFS: Server returned error %d "
+ "while mounting %s\n", status, nfs_path);
- return 0;
+ return status;
}
@@ -1673,23 +1514,12 @@
*/
static int root_nfs_do_mount(struct super_block *sb)
{
- /* First connect to the nfsd port on the server */
- server.sin_port = htons(nfs_port);
- nfs_data.addr = server;
- if (nfs_sock_inode->u.socket_i.ops->connect &&
- nfs_sock_inode->u.socket_i.ops->connect(&nfs_sock_inode->u.socket_i,
- (struct sockaddr *) &server,
- sizeof(struct sockaddr_in),
- nfs_file->f_flags) < 0) {
- root_nfs_close();
- return -1;
- }
+ /* Pass the server address to NFS */
+ set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, nfs_port);
/* Now (finally ;-)) read the super block for mounting */
- if (nfs_read_super(sb, &nfs_data, 1) == NULL) {
- root_nfs_close();
+ if (nfs_read_super(sb, &nfs_data, 1) == NULL)
return -1;
- }
return 0;
}
@@ -1700,16 +1530,11 @@
*/
int nfs_root_mount(struct super_block *sb)
{
- if (root_nfs_open() < 0)
- return -1;
- if (root_nfs_bind() < 0)
- return -1;
if (root_nfs_ports() < 0)
return -1;
if (root_nfs_get_handle() < 0)
return -1;
if (root_nfs_do_mount(sb) < 0)
return -1;
- root_nfs_close();
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov