mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 17:18:32 +00:00
Add IPv6 support.
Submitted by: Jean-Luc Richier <Jean-Luc.Richier@imag.fr>
This commit is contained in:
parent
702b2a722b
commit
09ce4f7aaf
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=100134
|
@ -6,8 +6,10 @@ SRCS= vnode_if.h \
|
|||
nfs_bio.c nfs_lock.c nfs_node.c nfs_socket.c nfs_subs.c nfs_nfsiod.c \
|
||||
nfs_vfsops.c nfs_vnops.c nfs_common.c \
|
||||
opt_inet.h opt_nfs.h opt_bootp.h
|
||||
SRCS+= opt_inet6.h
|
||||
|
||||
NFS_INET?= 1 # 0/1 - requires INET to be configured in kernel
|
||||
NFS_INET6?= 1 # 0/1 - requires INET6 to be configured in kernel
|
||||
|
||||
opt_inet.h:
|
||||
touch ${.TARGET}
|
||||
|
@ -15,4 +17,10 @@ opt_inet.h:
|
|||
echo "#define INET 1" > ${.TARGET}
|
||||
.endif
|
||||
|
||||
.if ${NFS_INET6} > 0
|
||||
opt_inet6.h:
|
||||
echo "#define INET6 1" > ${.TARGET}
|
||||
.endif
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
||||
|
|
|
@ -6,5 +6,12 @@ SRCS= vnode_if.h \
|
|||
nfs_serv.c nfs_srvsock.c nfs_srvcache.c nfs_srvsubs.c nfs_syscalls.c \
|
||||
nfs_common.c \
|
||||
opt_nfs.h
|
||||
SRCS+= opt_inet6.h
|
||||
NFS_INET6?= 1 # 0/1 - requires INET6 to be configured in kernel
|
||||
|
||||
.if ${NFS_INET6} > 0
|
||||
opt_inet6.h:
|
||||
echo "#define INET6 1" > ${.TARGET}
|
||||
.endif
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
|
|
@ -130,13 +130,12 @@ nfs_dolock(struct vop_advlock_args *ap)
|
|||
msg.lm_wait = ap->a_flags & F_WAIT;
|
||||
msg.lm_getlk = ap->a_op == F_GETLK;
|
||||
/*
|
||||
* XXX -- I think this is wrong for anything other AF_INET.
|
||||
*
|
||||
* XXX: the lm_cred assignment below directly exports a ucred
|
||||
* structure to userland. This is probably wrong, and should at
|
||||
* least be xucred.
|
||||
*/
|
||||
msg.lm_addr = *(VFSTONFS(vp->v_mount)->nm_nam);
|
||||
bcopy(VFSTONFS(vp->v_mount)->nm_nam, &msg.lm_addr,
|
||||
min(sizeof msg.lm_addr, VFSTONFS(vp->v_mount)->nm_nam->sa_len));
|
||||
msg.lm_fh_len = NFS_ISV3(vp) ? VTONFS(vp)->n_fhsize : NFSX_V2FH;
|
||||
bcopy(VTONFS(vp)->n_fhp, msg.lm_fh, msg.lm_fh_len);
|
||||
msg.lm_nfsv3 = NFS_ISV3(vp);
|
||||
|
|
|
@ -58,7 +58,7 @@ struct lockd_msg_ident {
|
|||
int msg_seq; /* Sequence number of message */
|
||||
};
|
||||
|
||||
#define LOCKD_MSG_VERSION 1
|
||||
#define LOCKD_MSG_VERSION 2
|
||||
|
||||
/*
|
||||
* The structure that the kernel hands us for each lock request.
|
||||
|
@ -69,7 +69,7 @@ typedef struct __lock_msg {
|
|||
struct flock lm_fl; /* The lock request. */
|
||||
int lm_wait; /* The F_WAIT flag. */
|
||||
int lm_getlk; /* is this a F_GETLK request */
|
||||
struct sockaddr lm_addr; /* The address. */
|
||||
struct sockaddr_storage lm_addr; /* The address. */
|
||||
int lm_nfsv3; /* If NFS version 3. */
|
||||
size_t lm_fh_len; /* The file handle length. */
|
||||
struct ucred lm_cred; /* user cred for lock req */
|
||||
|
|
|
@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$");
|
|||
* Socket operations for use by nfs
|
||||
*/
|
||||
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
|
@ -157,7 +159,6 @@ nfs_connect(struct nfsmount *nmp, struct nfsreq *rep)
|
|||
int s, error, rcvreserve, sndreserve;
|
||||
int pktscale;
|
||||
struct sockaddr *saddr;
|
||||
struct sockaddr_in *sin;
|
||||
struct thread *td = &thread0; /* only used for socreate and sobind */
|
||||
|
||||
nmp->nm_so = NULL;
|
||||
|
@ -172,42 +173,51 @@ nfs_connect(struct nfsmount *nmp, struct nfsreq *rep)
|
|||
/*
|
||||
* Some servers require that the client port be a reserved port number.
|
||||
*/
|
||||
if (saddr->sa_family == AF_INET && (nmp->nm_flag & NFSMNT_RESVPORT)) {
|
||||
if (nmp->nm_flag & NFSMNT_RESVPORT) {
|
||||
struct sockopt sopt;
|
||||
int ip;
|
||||
struct sockaddr_in ssin;
|
||||
int ip, ip2, len;
|
||||
struct sockaddr_in6 ssin;
|
||||
struct sockaddr *sa;
|
||||
|
||||
bzero(&sopt, sizeof sopt);
|
||||
ip = IP_PORTRANGE_LOW;
|
||||
switch(saddr->sa_family) {
|
||||
case AF_INET:
|
||||
sopt.sopt_level = IPPROTO_IP;
|
||||
sopt.sopt_name = IP_PORTRANGE;
|
||||
ip = IP_PORTRANGE_LOW;
|
||||
ip2 = IP_PORTRANGE_DEFAULT;
|
||||
len = sizeof (struct sockaddr_in);
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
sopt.sopt_level = IPPROTO_IPV6;
|
||||
sopt.sopt_name = IPV6_PORTRANGE;
|
||||
ip = IPV6_PORTRANGE_LOW;
|
||||
ip2 = IPV6_PORTRANGE_DEFAULT;
|
||||
len = sizeof (struct sockaddr_in6);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
goto noresvport;
|
||||
}
|
||||
sa = (struct sockaddr *)&ssin;
|
||||
bzero(sa, len);
|
||||
sa->sa_len = len;
|
||||
sa->sa_family = saddr->sa_family;
|
||||
sopt.sopt_dir = SOPT_SET;
|
||||
sopt.sopt_level = IPPROTO_IP;
|
||||
sopt.sopt_name = IP_PORTRANGE;
|
||||
sopt.sopt_val = (void *)&ip;
|
||||
sopt.sopt_valsize = sizeof(ip);
|
||||
sopt.sopt_td = NULL;
|
||||
error = sosetopt(so, &sopt);
|
||||
if (error)
|
||||
goto bad;
|
||||
bzero(&ssin, sizeof ssin);
|
||||
sin = &ssin;
|
||||
sin->sin_len = sizeof (struct sockaddr_in);
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_addr.s_addr = INADDR_ANY;
|
||||
sin->sin_port = htons(0);
|
||||
error = sobind(so, (struct sockaddr *)sin, td);
|
||||
error = sobind(so, sa, td);
|
||||
if (error)
|
||||
goto bad;
|
||||
bzero(&sopt, sizeof sopt);
|
||||
ip = IP_PORTRANGE_DEFAULT;
|
||||
sopt.sopt_dir = SOPT_SET;
|
||||
sopt.sopt_level = IPPROTO_IP;
|
||||
sopt.sopt_name = IP_PORTRANGE;
|
||||
sopt.sopt_val = (void *)&ip;
|
||||
sopt.sopt_valsize = sizeof(ip);
|
||||
sopt.sopt_td = NULL;
|
||||
ip = ip2;
|
||||
error = sosetopt(so, &sopt);
|
||||
if (error)
|
||||
goto bad;
|
||||
noresvport: ;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -195,13 +195,6 @@ union nethostaddr {
|
|||
struct sockaddr *had_nam;
|
||||
};
|
||||
|
||||
#define nu_inetaddr nu_haddr.had_inetaddr
|
||||
#define nu_nam nu_haddr.had_nam
|
||||
/* Bits for nu_flag */
|
||||
#define NU_INETADDR 0x1
|
||||
#define NU_NAM 0x2
|
||||
#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
|
||||
|
||||
struct nfsrv_rec {
|
||||
STAILQ_ENTRY(nfsrv_rec) nr_link;
|
||||
struct sockaddr *nr_address;
|
||||
|
|
|
@ -71,7 +71,7 @@ static u_long nfsrvhash;
|
|||
#define FALSE 0
|
||||
|
||||
#define NETFAMILY(rp) \
|
||||
(((rp)->rc_flag & RC_INETADDR) ? AF_INET : AF_ISO)
|
||||
(((rp)->rc_flag & RC_NAM) ? (rp)->rc_nam->sa_family : AF_INET)
|
||||
|
||||
/*
|
||||
* Static array that defines which nfs rpc's are nonidempotent
|
||||
|
@ -240,7 +240,8 @@ nfsrv_getcache(struct nfsrv_descript *nd, struct mbuf **repp)
|
|||
rp->rc_flag |= RC_INETADDR;
|
||||
rp->rc_inetaddr = saddr->sin_addr.s_addr;
|
||||
break;
|
||||
case AF_ISO:
|
||||
/* case AF_INET6: */
|
||||
/* case AF_ISO: */
|
||||
default:
|
||||
rp->rc_flag |= RC_NAM;
|
||||
rp->rc_nam = dup_sockaddr(nd->nd_nam, 1);
|
||||
|
|
|
@ -154,13 +154,13 @@ nfs_rephead(int siz, struct nfsrv_descript *nd, int err,
|
|||
* If this is a big reply, use a cluster else
|
||||
* try and leave leading space for the lower level headers.
|
||||
*/
|
||||
mreq->m_len = 6 * NFSX_UNSIGNED;
|
||||
siz += RPC_REPLYSIZ;
|
||||
if ((max_hdr + siz) >= MINCLSIZE) {
|
||||
MCLGET(mreq, M_TRYWAIT);
|
||||
} else
|
||||
mreq->m_data += max_hdr;
|
||||
mreq->m_data += min(max_hdr, M_TRAILINGSPACE(mreq));
|
||||
tl = mtod(mreq, u_int32_t *);
|
||||
mreq->m_len = 6 * NFSX_UNSIGNED;
|
||||
bpos = ((caddr_t)tl) + mreq->m_len;
|
||||
*tl++ = txdr_unsigned(nd->nd_retxid);
|
||||
*tl++ = nfsrv_rpc_reply;
|
||||
|
|
|
@ -46,6 +46,8 @@ __FBSDID("$FreeBSD$");
|
|||
* copy data between mbuf chains and uio lists.
|
||||
*/
|
||||
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
|
@ -1051,7 +1053,9 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp,
|
|||
#ifdef MNT_EXNORESPORT
|
||||
if (!(exflags & (MNT_EXNORESPORT|MNT_EXPUBLIC))) {
|
||||
saddr = (struct sockaddr_in *)nam;
|
||||
if (saddr->sin_family == AF_INET &&
|
||||
if ((saddr->sin_family == AF_INET ||
|
||||
saddr->sin_family == AF_INET6) &&
|
||||
/* same code for INET and INET6: sin*_port at same offet */
|
||||
ntohs(saddr->sin_port) >= IPPORT_RESERVED) {
|
||||
vput(*vpp);
|
||||
*vpp = NULL;
|
||||
|
@ -1117,6 +1121,21 @@ netaddr_match(int family, union nethostaddr *haddr, struct sockaddr *nam)
|
|||
inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
|
||||
return (1);
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
register struct sockaddr_in6 *inet6addr1, *inet6addr2;
|
||||
|
||||
inet6addr1 = (struct sockaddr_in6 *)nam;
|
||||
inet6addr2 = (struct sockaddr_in6 *)haddr->had_nam;
|
||||
/* XXX - should test sin6_scope_id ? */
|
||||
if (inet6addr1->sin6_family == AF_INET6 &&
|
||||
IN6_ARE_ADDR_EQUAL(&inet6addr1->sin6_addr,
|
||||
&inet6addr2->sin6_addr))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/sysproto.h>
|
||||
|
@ -64,6 +66,10 @@ __FBSDID("$FreeBSD$");
|
|||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#ifdef INET6
|
||||
#include <net/if.h>
|
||||
#include <netinet6/in6_var.h>
|
||||
#endif
|
||||
#include <nfs/xdr_subs.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
|
@ -109,6 +115,10 @@ static int nfssvc_nfsd(struct nfsd_srvargs *, caddr_t, struct thread *);
|
|||
* - adds a socket to the selection list
|
||||
* - remains in the kernel as an nfsd
|
||||
* - remains in the kernel as an nfsiod
|
||||
* For INET6 we suppose that nfsd provides only IN6P_BINDV6ONLY sockets
|
||||
* and that mountd provides
|
||||
* - sockaddr with no IPv4-mapped addresses
|
||||
* - mask for both INET and INET6 families if there is IPv4-mapped overlap
|
||||
*/
|
||||
#ifndef _SYS_SYSPROTO_H_
|
||||
struct nfssvc_args {
|
||||
|
@ -230,8 +240,7 @@ nfssvc_addsock(struct file *fp, struct sockaddr *mynam, struct thread *td)
|
|||
val = 1;
|
||||
sosetopt(so, &sopt);
|
||||
}
|
||||
if (so->so_proto->pr_domain->dom_family == AF_INET &&
|
||||
so->so_proto->pr_protocol == IPPROTO_TCP) {
|
||||
if (so->so_proto->pr_protocol == IPPROTO_TCP) {
|
||||
struct sockopt sopt;
|
||||
int val;
|
||||
|
||||
|
@ -385,13 +394,33 @@ nfssvc_nfsd(struct nfsd_srvargs *nsd, caddr_t argp, struct thread *td)
|
|||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)nam;
|
||||
/*
|
||||
* INET/INET6 - same code:
|
||||
* sin_port and sin6_port are at same offset
|
||||
*/
|
||||
port = ntohs(sin->sin_port);
|
||||
if (port >= IPPORT_RESERVED &&
|
||||
nd->nd_procnum != NFSPROC_NULL) {
|
||||
#if defined(INET6) && defined(KLD_MODULE)
|
||||
/* do not use ip6_sprintf: the nfs module should work without INET6 */
|
||||
char b6[INET6_ADDRSTRLEN];
|
||||
#define ip6_sprintf(a) \
|
||||
(sprintf(b6, "%x:%x:%x:%x:%x:%x:%x:%x", \
|
||||
(a)->s6_addr16[0], (a)->s6_addr16[1], \
|
||||
(a)->s6_addr16[2], (a)->s6_addr16[3], \
|
||||
(a)->s6_addr16[4], (a)->s6_addr16[5], \
|
||||
(a)->s6_addr16[6], (a)->s6_addr16[7]), \
|
||||
b6)
|
||||
#endif
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
|
||||
cacherep = RC_DOIT;
|
||||
printf("NFS request from unprivileged port (%s:%d)\n",
|
||||
#ifdef INET6
|
||||
sin->sin_family == AF_INET6 ?
|
||||
ip6_sprintf(&satosin6(sin)->sin6_addr) :
|
||||
#undef ip6_sprintf
|
||||
#endif
|
||||
inet_ntoa(sin->sin_addr), port);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "nlm_prot.h"
|
||||
#include <nfs/rpcv2.h>
|
||||
|
@ -87,8 +88,17 @@ int unlock_request(LOCKD_MSG *);
|
|||
#define d_calls (debug_level > 1)
|
||||
#define d_args (debug_level > 2)
|
||||
|
||||
#define from_addr(sockaddr) \
|
||||
(inet_ntoa((sockaddr)->sin_addr))
|
||||
static const char *
|
||||
from_addr(saddr)
|
||||
struct sockaddr *saddr;
|
||||
{
|
||||
static char inet_buf[INET6_ADDRSTRLEN];
|
||||
|
||||
if (getnameinfo(saddr, saddr->sa_len, inet_buf, sizeof(inet_buf),
|
||||
NULL, 0, NI_NUMERICHOST) == 0)
|
||||
return inet_buf;
|
||||
return "???";
|
||||
}
|
||||
|
||||
void
|
||||
client_cleanup(void)
|
||||
|
@ -257,7 +267,7 @@ test_request(LOCKD_MSG *msg)
|
|||
syslog(LOG_DEBUG, "test request: %s: %s to %s",
|
||||
msg->lm_nfsv3 ? "V4" : "V1/3",
|
||||
msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
|
||||
from_addr((struct sockaddr_in *)&msg->lm_addr));
|
||||
from_addr((struct sockaddr *)&msg->lm_addr));
|
||||
|
||||
if (msg->lm_nfsv3) {
|
||||
struct nlm4_testargs arg4;
|
||||
|
@ -326,7 +336,7 @@ lock_request(LOCKD_MSG *msg)
|
|||
syslog(LOG_DEBUG, "lock request: %s: %s to %s",
|
||||
msg->lm_nfsv3 ? "V4" : "V1/3",
|
||||
msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
|
||||
from_addr((struct sockaddr_in *)&msg->lm_addr));
|
||||
from_addr((struct sockaddr *)&msg->lm_addr));
|
||||
|
||||
if (msg->lm_nfsv3) {
|
||||
arg4.cookie.n_bytes = (char *)&msg->lm_msg_ident;
|
||||
|
@ -396,7 +406,7 @@ unlock_request(LOCKD_MSG *msg)
|
|||
if (d_calls)
|
||||
syslog(LOG_DEBUG, "unlock request: %s: to %s",
|
||||
msg->lm_nfsv3 ? "V4" : "V1/3",
|
||||
from_addr((struct sockaddr_in *)&msg->lm_addr));
|
||||
from_addr((struct sockaddr *)&msg->lm_addr));
|
||||
|
||||
if (msg->lm_nfsv3) {
|
||||
arg4.cookie.n_bytes = (char *)&msg->lm_msg_ident;
|
||||
|
|
Loading…
Reference in a new issue