Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 31 May 2016 17:15:57 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r301057 - stable/10/sys/nfs
Message-ID:  <201605311715.u4VHFvMg012177@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Tue May 31 17:15:57 2016
New Revision: 301057
URL: https://svnweb.freebsd.org/changeset/base/301057

Log:
  MFC r297323,r297324, r297325, r297326:
  
    Set only one default route for nfsroot mount, the one associated with the
    interface that will be used to mount the rootfs (and never a self-ip proxy
    arp route).  Made up of the following related changes...
  
    Set ifctx->gotrootpath=1 only when the root path came from the dhcp/bootp
    server (and not when it came from a fallback method such as the ROOTDEVNAME
    option).  This makes the code in bootpc_init() choose the first interface
    that provided a rootpath name.  Previously it was choosing the first
    interface that got an IP address, which could be on a different and
    potentially unreachable subnet than the server providing the rootfs.
  
    If the rootpath name actually does come from a fallback source, then the
    code continues to use the first interface in the list that got configured.
    Note that this wasn't directly reported in the PR cited below, but was
    discovered while working on that PR.
  
    Switch bootpc_adjust_interface() from returning int to void.  Its one caller
    doesn't check for errors, and all the errors that can happen result in it
    calling panic anyway, except for one that's really more of a warning (and
    is going to disappear on an upcoming commit anyway).
  
    Stop setting the default route to the IP of the interface itself when the
    bootp/dhcp server doesn't provide a router option.  Doing so prevents
    setting defaultrouter=<ip> in rc.conf (it fails because there's already
    a bogus default route installed by bootpc_init).
  
    When an admin wants to use this style of proxy arp on an interface, the
    proper mechanism is to set the "use-lease-addr-for-default-route" flag
    in the dhcp server config.  That causes the lease address to be delivered
    in the routers option, and the normal handling of the routers option will
    then install the self-ip as the default route.
  
    Do not try to install a default route for each interface found, because
    only the first one will actually work and all the others just result in
    errors (which would get printed but otherwise ignored).
  
    Instead, wait until we make a choice of which interface will be used to
    mount the rootfs, and install the default route associated with it (if any).
    After doing the md_mount() call to obtain the needed info, remove the
    default route again, and transcribe the route info into the nfs_diskless
    structure.  If the system eventually chooses to mount the nfs rootfs, the
    default route will be installed again when the nfs_diskless code
    re-initializes the interface.
  
  PR:		187094

Modified:
  stable/10/sys/nfs/bootp_subr.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/nfs/bootp_subr.c
==============================================================================
--- stable/10/sys/nfs/bootp_subr.c	Tue May 31 17:01:54 2016	(r301056)
+++ stable/10/sys/nfs/bootp_subr.c	Tue May 31 17:15:57 2016	(r301057)
@@ -272,7 +272,7 @@ static int	bootpc_call(struct bootpc_glo
 static void	bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
 		    struct thread *td);
 
-static int	bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
+static void	bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
 		    struct bootpc_globalcontext *gctx, struct thread *td);
 
 static void	bootpc_decode_reply(struct nfsv3_diskless *nd,
@@ -1007,30 +1007,26 @@ bootpc_shutdown_interface(struct bootpc_
 		panic("%s: SIOCDIFADDR, error=%d", __func__, error);
 }
 
-static int
+static void
 bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
     struct bootpc_globalcontext *gctx, struct thread *td)
 {
 	int error;
-	struct sockaddr_in defdst;
-	struct sockaddr_in defmask;
 	struct sockaddr_in *sin;
 	struct ifreq *ifr;
 	struct in_aliasreq *ifra;
 	struct sockaddr_in *myaddr;
 	struct sockaddr_in *netmask;
-	struct sockaddr_in *gw;
 
 	ifr = &ifctx->ireq;
 	ifra = &ifctx->iareq;
 	myaddr = &ifctx->myaddr;
 	netmask = &ifctx->netmask;
-	gw = &ifctx->gw;
 
 	if (bootpc_ifctx_isresolved(ifctx) == 0) {
 		/* Shutdown interfaces where BOOTP failed */
 		bootpc_shutdown_interface(ifctx, td);
-		return (0);
+		return;
 	}
 
 	printf("Adjusted interface %s", ifctx->ireq.ifr_name);
@@ -1065,24 +1061,48 @@ bootpc_adjust_interface(struct bootpc_if
 	error = ifioctl(bootp_so, SIOCAIFADDR, (caddr_t)ifra, td);
 	if (error != 0)
 		panic("%s: SIOCAIFADDR, error=%d", __func__, error);
+}
+
+static void
+bootpc_add_default_route(struct bootpc_ifcontext *ifctx)
+{
+	int error;
+	struct sockaddr_in defdst;
+	struct sockaddr_in defmask;
 
-	/* Add new default route */
+	if (ifctx->gw.sin_addr.s_addr == htonl(INADDR_ANY))
+		return;
 
-	if (ifctx->gotgw != 0 || gctx->gotgw == 0) {
-		clear_sinaddr(&defdst);
-		clear_sinaddr(&defmask);
-		/* XXX MRT just table 0 */
-		error = rtrequest_fib(RTM_ADD,
-		    (struct sockaddr *) &defdst, (struct sockaddr *) gw,
-		    (struct sockaddr *) &defmask,
-		    (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, RT_DEFAULT_FIB);
-		if (error != 0) {
-			printf("%s: RTM_ADD, error=%d\n", __func__, error);
-			return (error);
-		}
+	clear_sinaddr(&defdst);
+	clear_sinaddr(&defmask);
+
+	error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&defdst,
+	    (struct sockaddr *) &ifctx->gw, (struct sockaddr *)&defmask,
+	    (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, RT_DEFAULT_FIB);
+	if (error != 0) {
+		printf("%s: RTM_ADD, error=%d\n", __func__, error);
 	}
+}
+
+static void
+bootpc_remove_default_route(struct bootpc_ifcontext *ifctx)
+{
+	int error;
+	struct sockaddr_in defdst;
+	struct sockaddr_in defmask;
 
-	return (0);
+	if (ifctx->gw.sin_addr.s_addr == htonl(INADDR_ANY))
+		return;
+
+	clear_sinaddr(&defdst);
+	clear_sinaddr(&defmask);
+
+	error = rtrequest_fib(RTM_DELETE, (struct sockaddr *)&defdst,
+	    (struct sockaddr *) &ifctx->gw, (struct sockaddr *)&defmask,
+	    (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, RT_DEFAULT_FIB);
+	if (error != 0) {
+		printf("%s: RTM_DELETE, error=%d\n", __func__, error);
+	}
 }
 
 static int
@@ -1474,6 +1494,8 @@ bootpc_decode_reply(struct nfsv3_diskles
 	if (p == NULL) {
 		p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
 		       TAG_ROOT);
+		if (p != NULL)
+			ifctx->gotrootpath = 1;
 	}
 #ifdef ROOTDEVNAME
 	if ((p == NULL || (boothowto & RB_DFLTROOT) != 0) && 
@@ -1493,7 +1515,6 @@ bootpc_decode_reply(struct nfsv3_diskles
 			}
 			printf("rootfs %s ", p);
 			gctx->gotrootpath = 1;
-			ifctx->gotrootpath = 1;
 			gctx->setrootfs = ifctx;
 
 			p = bootpc_tag(&gctx->tag, &ifctx->reply,
@@ -1549,10 +1570,6 @@ bootpc_decode_reply(struct nfsv3_diskles
 		else
 			ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET);
 	}
-	if (ifctx->gotgw == 0) {
-		/* Use proxyarp */
-		ifctx->gw.sin_addr.s_addr = ifctx->myaddr.sin_addr.s_addr;
-	}
 }
 
 void
@@ -1744,9 +1761,11 @@ retry:
 
 		setenv("boot.netif.name", ifctx->ifp->if_xname);
 
+		bootpc_add_default_route(ifctx);
 		error = md_mount(&nd->root_saddr, nd->root_hostnam,
 				 nd->root_fh, &nd->root_fhsize,
 				 &nd->root_args, td);
+		bootpc_remove_default_route(ifctx);
 		if (error != 0) {
 			if (gctx->any_root_overrides == 0)
 				panic("nfs_boot: mount root, error=%d", error);
@@ -1767,6 +1786,7 @@ retry:
 		ifctx->myaddr.sin_addr.s_addr |
 		~ ifctx->netmask.sin_addr.s_addr;
 	bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask));
+	bcopy(&ifctx->gw, &nd->mygateway, sizeof(ifctx->gw));
 
 out:
 	while((ifctx = STAILQ_FIRST(&gctx->interfaces)) != NULL) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201605311715.u4VHFvMg012177>