>I've had some problems with this as well- at least I think it is the same
>problem. The source of the problem is NFS mounting from servers that
>have more than one network interface. In newer kernels, NFS packets
>seem to be accepted only from the interface which negotiated the original
>mount. This behaviour has been the source of much contention of the
>KERNEL and NET mailing lists, with Linus firmly supporting the present
>(annoying) behaviour, as anything else is spoofable and a security risk.
Well, here is a RealSolution^TM, which is unfortunately not (yet)Quote:>Unfortunately, changes in routing can happen dynamically and may change
>which interface packets are coming from,
>We need a real solution.
accepted by Linus. You need to apply the following kernel patch, AND
you will have to patch the mount program (and the automounter amd as
well, if you are using it). Applying the kernel patch alone will not
change the current behaviour. You can find the source to mount in
util-linux-1.10.tar.gz. In the file nfsmount.c, remove or #ifdef 0 the
following code fragment (should be around line 350):
if (connect(fsock, (struct sockaddr *) &server_addr,
sizeof (server_addr)) < 0) {
perror("nfs connect");
goto fail;
}
Note, that this change will make the mount program incompatible with
older kernels or kernels without the patch below. You could test for
the kernel release with some code like this:
uname(&my_utsname)
if (strcmp(my_utsname.release, "1.1.83") < 0)
{
/* code with connect() */
}
else
{
/* code without connect() */
}
Unfortunately, you have to do this yourself, since Linus refused to
put in the patch below into the official kernel, so there is no
definite release which could go into the mount program to keep it
compatible. Perhaps you (Yes, I mean _YOU_) can convince Linus, that
this patch is no security hole (perhaps we can add an option to the
mount program, which will connect() the socket regardless of the
kernel revision for security).
Greetings, Swen
Here's the patch. Apply with "cd /usr/src; patch -p < whateveryounamedit"
diff -u -r linux.orig/fs/nfs/inode.c linux/fs/nfs/inode.c
--- linux.orig/fs/nfs/inode.c Tue Jan 10 16:02:18 1995
server->acdirmin = data->acdirmin*HZ;
server->acdirmax = data->acdirmax*HZ;
strcpy(server->hostname, data->hostname);
+ memcpy(&server->addr, &data->addr, sizeof(struct sockaddr_in));
sb->u.nfs_sb.s_root = data->root;
unlock_super(sb);
if (!(sb->s_mounted = nfs_fhget(sb, &data->root, NULL))) {
diff -u -r linux.orig/fs/nfs/sock.c linux/fs/nfs/sock.c
--- linux.orig/fs/nfs/sock.c Thu Jan 5 12:55:40 1995
fs = get_fs();
set_fs(get_ds());
for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) {
- result = sock->ops->send(sock, (void *) start, len, 0, 0);
+ result = sock->ops->sendto(sock, (void *) start, len, 0, 0, (struct sockaddr *)&server->addr, sizeof(server->addr));
if (result < 0) {
printk("nfs_rpc_call: send error = %d\n", result);
* we don't now need, so discard it */
result = sock->ops->recvfrom(sock, (void *)&recv_xid,
sizeof(recv_xid), 1, MSG_PEEK,
- NULL, &addrlen);
+ NULL, NULL);
if (result < 0) {
if (result == -EAGAIN) {
* a null buffer yet. */
(void)sock->ops->recvfrom(sock, (void *)&recv_xid,
sizeof(recv_xid), 1, 0, NULL,
- &addrlen);
+ NULL);
#if 0
printk("nfs_rpc_call: XID mismatch\n");
*
*/
result=sock->ops->recvfrom(sock, (void *)start,
- size + 1024, 1, 0, NULL,
+ size + 1024, 1, 0, (struct sockaddr *)&server->addr,
/* Here is NFS_SLACK_SPACE..., hack */
&addrlen);
if (result < 0) {
diff -u -r linux.orig/include/linux/nfs_fs_sb.h linux/include/linux/nfs_fs_sb.h
--- linux.orig/include/linux/nfs_fs_sb.h Wed Dec 1 13:44:15 1993
#define _NFS_FS_SB
#include <linux/nfs.h>
+#include <linux/in.h>
struct nfs_server {
int acdirmin;
int acdirmax;
char hostname[256];
+ struct sockaddr_in addr;
};
/*