diff options
author | alfred <alfred@FreeBSD.org> | 2002-07-15 19:40:23 +0000 |
---|---|---|
committer | alfred <alfred@FreeBSD.org> | 2002-07-15 19:40:23 +0000 |
commit | df766765ba15b2a418b09b713353a763a1c12909 (patch) | |
tree | 08c1766490b20ea5dcdd86157dd05bf33f410b18 | |
parent | c559b8902789e64b5a4b1e482f230e933cda7198 (diff) | |
download | FreeBSD-src-df766765ba15b2a418b09b713353a763a1c12909.zip FreeBSD-src-df766765ba15b2a418b09b713353a763a1c12909.tar.gz |
Add IPv6 support.
Submitted by: Jean-Luc Richier <Jean-Luc.Richier@imag.fr>
-rw-r--r-- | sys/modules/nfsclient/Makefile | 8 | ||||
-rw-r--r-- | sys/modules/nfsserver/Makefile | 7 | ||||
-rw-r--r-- | sys/nfsclient/nfs_lock.c | 5 | ||||
-rw-r--r-- | sys/nfsclient/nfs_lock.h | 4 | ||||
-rw-r--r-- | sys/nfsclient/nfs_socket.c | 56 | ||||
-rw-r--r-- | sys/nfsserver/nfs.h | 7 | ||||
-rw-r--r-- | sys/nfsserver/nfs_srvcache.c | 5 | ||||
-rw-r--r-- | sys/nfsserver/nfs_srvsock.c | 4 | ||||
-rw-r--r-- | sys/nfsserver/nfs_srvsubs.c | 21 | ||||
-rw-r--r-- | sys/nfsserver/nfs_syscalls.c | 33 | ||||
-rw-r--r-- | usr.sbin/rpc.lockd/kern.c | 20 |
11 files changed, 123 insertions, 47 deletions
diff --git a/sys/modules/nfsclient/Makefile b/sys/modules/nfsclient/Makefile index 55fcd88..0d2505a 100644 --- a/sys/modules/nfsclient/Makefile +++ b/sys/modules/nfsclient/Makefile @@ -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> + diff --git a/sys/modules/nfsserver/Makefile b/sys/modules/nfsserver/Makefile index 89d9664..e57ac6e 100644 --- a/sys/modules/nfsserver/Makefile +++ b/sys/modules/nfsserver/Makefile @@ -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> diff --git a/sys/nfsclient/nfs_lock.c b/sys/nfsclient/nfs_lock.c index 0c9d6ac..dfd5ed0 100644 --- a/sys/nfsclient/nfs_lock.c +++ b/sys/nfsclient/nfs_lock.c @@ -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); diff --git a/sys/nfsclient/nfs_lock.h b/sys/nfsclient/nfs_lock.h index 9de041d..af99bc5 100644 --- a/sys/nfsclient/nfs_lock.h +++ b/sys/nfsclient/nfs_lock.h @@ -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 */ diff --git a/sys/nfsclient/nfs_socket.c b/sys/nfsclient/nfs_socket.c index 5966f38..496cbe4 100644 --- a/sys/nfsclient/nfs_socket.c +++ b/sys/nfsclient/nfs_socket.c @@ -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: ; } /* diff --git a/sys/nfsserver/nfs.h b/sys/nfsserver/nfs.h index 18768af..cbdb54f 100644 --- a/sys/nfsserver/nfs.h +++ b/sys/nfsserver/nfs.h @@ -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; diff --git a/sys/nfsserver/nfs_srvcache.c b/sys/nfsserver/nfs_srvcache.c index 2222ffa..1986c0b 100644 --- a/sys/nfsserver/nfs_srvcache.c +++ b/sys/nfsserver/nfs_srvcache.c @@ -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 @@ loop: 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); diff --git a/sys/nfsserver/nfs_srvsock.c b/sys/nfsserver/nfs_srvsock.c index 2143544..1feffa9 100644 --- a/sys/nfsserver/nfs_srvsock.c +++ b/sys/nfsserver/nfs_srvsock.c @@ -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; diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c index 5f37b1f..19a74d7 100644 --- a/sys/nfsserver/nfs_srvsubs.c +++ b/sys/nfsserver/nfs_srvsubs.c @@ -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; }; diff --git a/sys/nfsserver/nfs_syscalls.c b/sys/nfsserver/nfs_syscalls.c index fb60d36..f123dcc 100644 --- a/sys/nfsserver/nfs_syscalls.c +++ b/sys/nfsserver/nfs_syscalls.c @@ -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); } } diff --git a/usr.sbin/rpc.lockd/kern.c b/usr.sbin/rpc.lockd/kern.c index e79cfb0..5eb9413 100644 --- a/usr.sbin/rpc.lockd/kern.c +++ b/usr.sbin/rpc.lockd/kern.c @@ -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; |