diff options
author | ian <ian@FreeBSD.org> | 2016-05-31 17:15:57 +0000 |
---|---|---|
committer | ian <ian@FreeBSD.org> | 2016-05-31 17:15:57 +0000 |
commit | 801afed4d05a94621bc993ab5c2982b1a3bc27ae (patch) | |
tree | b9ec305bb2d3684c155f3ca23c82f63f68f9cf94 | |
parent | 0dfbd8e3cc8b9a97e27d9fb920bada3a7d2d5340 (diff) | |
download | FreeBSD-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.c | 72 |
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) { |