summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authormelifaro <melifaro@FreeBSD.org>2016-01-15 09:05:14 +0000
committermelifaro <melifaro@FreeBSD.org>2016-01-15 09:05:14 +0000
commit3243205726ff07ebda3838ff175142741910fb23 (patch)
tree2bce887e274d3a926d4064b7484a2c6ad1423741 /sys/fs
parent1600c49057326ff51510bcd7fbfa12702b47898c (diff)
downloadFreeBSD-src-3243205726ff07ebda3838ff175142741910fb23.zip
FreeBSD-src-3243205726ff07ebda3838ff175142741910fb23.tar.gz
Make nfscl_getmyip() use new routing KPI.
* Use standard IPv6 SAS instead of rt->rt_ifa address. * Make address lookup work for IPv6 LLA. * Save address into buffer provided by caller instead of using static vars. Discussed with: rmacklem
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/nfs/nfs_var.h2
-rw-r--r--sys/fs/nfsclient/nfs_clport.c102
-rw-r--r--sys/fs/nfsclient/nfs_clrpcops.c3
3 files changed, 52 insertions, 55 deletions
diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h
index 23475b2..3b494a5 100644
--- a/sys/fs/nfs/nfs_var.h
+++ b/sys/fs/nfs/nfs_var.h
@@ -306,7 +306,7 @@ void nfscl_reqstart(struct nfsrv_descript *, int, struct nfsmount *,
nfsuint64 *nfscl_getcookie(struct nfsnode *, off_t off, int);
void nfscl_fillsattr(struct nfsrv_descript *, struct vattr *,
vnode_t, int, u_int32_t);
-u_int8_t *nfscl_getmyip(struct nfsmount *, int *);
+u_int8_t *nfscl_getmyip(struct nfsmount *, struct in6_addr *, int *);
int nfsm_getfh(struct nfsrv_descript *, struct nfsfh **);
int nfscl_mtofh(struct nfsrv_descript *, struct nfsfh **,
struct nfsvattr *, int *);
diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c
index cdccbc8..4408506 100644
--- a/sys/fs/nfsclient/nfs_clport.c
+++ b/sys/fs/nfsclient/nfs_clport.c
@@ -34,6 +34,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_inet.h"
#include "opt_inet6.h"
#include <sys/capsicum.h>
@@ -46,7 +47,9 @@ __FBSDID("$FreeBSD$");
#include <sys/hash.h>
#include <sys/sysctl.h>
#include <fs/nfs/nfsport.h>
+#include <netinet/in_fib.h>
#include <netinet/if_ether.h>
+#include <netinet6/ip6_var.h>
#include <net/if_types.h>
#include <fs/nfsclient/nfs_kdtrace.h>
@@ -1038,73 +1041,66 @@ nfscl_loadfsinfo(struct nfsmount *nmp, struct nfsfsinfo *fsp)
}
/*
- * Get a pointer to my IP addrress and return it.
- * Return NULL if you can't find one.
+ * Lookups source address which should be used to communicate with
+ * @nmp and stores it inside @pdst.
+ *
+ * Returns 0 on success.
*/
u_int8_t *
-nfscl_getmyip(struct nfsmount *nmp, int *isinet6p)
+nfscl_getmyip(struct nfsmount *nmp, struct in6_addr *paddr, int *isinet6p)
{
- struct sockaddr_in sad, *sin;
- struct rtentry *rt;
- u_int8_t *retp = NULL;
- static struct in_addr laddr;
+ int error, fibnum;
- *isinet6p = 0;
- /*
- * Loop up a route for the destination address.
- */
+ fibnum = curthread->td_proc->p_fibnum;
+
+#ifdef INET
if (nmp->nm_nam->sa_family == AF_INET) {
- bzero(&sad, sizeof (sad));
+ struct sockaddr_in *sin;
+ struct nhop4_extended nh_ext;
+
sin = (struct sockaddr_in *)nmp->nm_nam;
- sad.sin_family = AF_INET;
- sad.sin_len = sizeof (struct sockaddr_in);
- sad.sin_addr.s_addr = sin->sin_addr.s_addr;
CURVNET_SET(CRED_TO_VNET(nmp->nm_sockreq.nr_cred));
- rt = rtalloc1_fib((struct sockaddr *)&sad, 0, 0UL,
- curthread->td_proc->p_fibnum);
- if (rt != NULL) {
- if (rt->rt_ifp != NULL &&
- rt->rt_ifa != NULL &&
- ((rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0) &&
- rt->rt_ifa->ifa_addr->sa_family == AF_INET) {
- sin = (struct sockaddr_in *)
- rt->rt_ifa->ifa_addr;
- laddr.s_addr = sin->sin_addr.s_addr;
- retp = (u_int8_t *)&laddr;
- }
- RTFREE_LOCKED(rt);
- }
+ error = fib4_lookup_nh_ext(fibnum, sin->sin_addr, 0, 0,
+ &nh_ext);
CURVNET_RESTORE();
+ if (error != 0)
+ return (NULL);
+
+ if ((ntohl(nh_ext.nh_src.s_addr) >> IN_CLASSA_NSHIFT) ==
+ IN_LOOPBACKNET) {
+ /* Ignore loopback addresses */
+ return (NULL);
+ }
+
+ *isinet6p = 0;
+ *((struct in_addr *)paddr) = nh_ext.nh_src;
+
+ return (u_int8_t *)paddr;
+ }
+#endif
#ifdef INET6
- } else if (nmp->nm_nam->sa_family == AF_INET6) {
- struct sockaddr_in6 sad6, *sin6;
- static struct in6_addr laddr6;
+ if (nmp->nm_nam->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6;
- bzero(&sad6, sizeof (sad6));
sin6 = (struct sockaddr_in6 *)nmp->nm_nam;
- sad6.sin6_family = AF_INET6;
- sad6.sin6_len = sizeof (struct sockaddr_in6);
- sad6.sin6_addr = sin6->sin6_addr;
+
CURVNET_SET(CRED_TO_VNET(nmp->nm_sockreq.nr_cred));
- rt = rtalloc1_fib((struct sockaddr *)&sad6, 0, 0UL,
- curthread->td_proc->p_fibnum);
- if (rt != NULL) {
- if (rt->rt_ifp != NULL &&
- rt->rt_ifa != NULL &&
- ((rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0) &&
- rt->rt_ifa->ifa_addr->sa_family == AF_INET6) {
- sin6 = (struct sockaddr_in6 *)
- rt->rt_ifa->ifa_addr;
- laddr6 = sin6->sin6_addr;
- retp = (u_int8_t *)&laddr6;
- *isinet6p = 1;
- }
- RTFREE_LOCKED(rt);
- }
+ error = in6_selectsrc_addr(fibnum, &sin6->sin6_addr,
+ sin6->sin6_scope_id, NULL, paddr, NULL);
CURVNET_RESTORE();
-#endif
+ if (error != 0)
+ return (NULL);
+
+ if (IN6_IS_ADDR_LOOPBACK(paddr))
+ return (NULL);
+
+ /* Scope is embedded in */
+ *isinet6p = 1;
+
+ return (u_int8_t *)paddr;
}
- return (retp);
+#endif
+ return (NULL);
}
/*
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index 7109944..a7d47f0 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -829,6 +829,7 @@ nfsrpc_setclient(struct nfsmount *nmp, struct nfsclclient *clp, int reclaim,
u_int32_t lease;
static u_int32_t rev = 0;
struct nfsclds *dsp, *ndsp, *tdsp;
+ struct in6_addr a6;
if (nfsboottime.tv_sec == 0)
NFSSETBOOTTIME(nfsboottime);
@@ -889,7 +890,7 @@ nfsrpc_setclient(struct nfsmount *nmp, struct nfsclclient *clp, int reclaim,
*tl = txdr_unsigned(NFS_CALLBCKPROG);
callblen = strlen(nfsv4_callbackaddr);
if (callblen == 0)
- cp = nfscl_getmyip(nmp, &isinet6);
+ cp = nfscl_getmyip(nmp, &a6, &isinet6);
if (nfscl_enablecallb && nfs_numnfscbd > 0 &&
(callblen > 0 || cp != NULL)) {
port = htons(nfsv4_cbport);
OpenPOWER on IntegriCloud