summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2016-05-31 17:15:57 +0000
committerian <ian@FreeBSD.org>2016-05-31 17:15:57 +0000
commit801afed4d05a94621bc993ab5c2982b1a3bc27ae (patch)
treeb9ec305bb2d3684c155f3ca23c82f63f68f9cf94
parent0dfbd8e3cc8b9a97e27d9fb920bada3a7d2d5340 (diff)
downloadFreeBSD-src-801afed4d05a94621bc993ab5c2982b1a3bc27ae.zip
FreeBSD-src-801afed4d05a94621bc993ab5c2982b1a3bc27ae.tar.gz
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
-rw-r--r--sys/nfs/bootp_subr.c72
1 files changed, 46 insertions, 26 deletions
diff --git a/sys/nfs/bootp_subr.c b/sys/nfs/bootp_subr.c
index 35b3fa4..7a2848a 100644
--- a/sys/nfs/bootp_subr.c
+++ b/sys/nfs/bootp_subr.c
@@ -272,7 +272,7 @@ static int bootpc_call(struct bootpc_globalcontext *gctx,
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_ifcontext *ifctx, struct thread *td)
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_ifcontext *ifctx,
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_diskless *nd, struct bootpc_ifcontext *ifctx,
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_diskless *nd, struct bootpc_ifcontext *ifctx,
}
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_diskless *nd, struct bootpc_ifcontext *ifctx,
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) {
OpenPOWER on IntegriCloud