void nfs_boot_cleanup(struct nfs_diskless *nd, struct lwp *lwp) { nfs_boot_deladdress(nd->nd_ifp, lwp, nd->nd_myip.s_addr); nfs_boot_ifupdown(nd->nd_ifp, lwp, 0); nfs_boot_flushrt(nd->nd_ifp); }
/* * Get client name, gateway address, then * get root and swap server:pathname info. * RPCs: bootparam/whoami, bootparam/getfile * * Use the old broadcast address for the WHOAMI * call because we do not yet know our netmask. * The server address returned by the WHOAMI call * is used for all subsequent bootparam RPCs. */ int nfs_bootparam(struct nfs_diskless *nd, struct lwp *lwp, int *flags) { struct ifnet *ifp = nd->nd_ifp; struct in_addr my_ip, arps_ip, gw_ip; struct sockaddr_in bp_sin; struct sockaddr_in *sin; #ifndef NFS_BOOTPARAM_NOGATEWAY struct nfs_dlmount *gw_ndm = 0; char *p; u_int32_t mask; #endif int error; /* * Bring up the interface. (just set the "up" flag) */ error = nfs_boot_ifupdown(ifp, lwp, 1); if (error) { printf("nfs_boot: SIFFLAGS, error=%d\n", error); return (error); } error = EADDRNOTAVAIL; #if NARP > 0 if (ifp->if_type == IFT_ETHER || ifp->if_type == IFT_FDDI) { /* * Do RARP for the interface address. */ error = revarpwhoarewe(ifp, &arps_ip, &my_ip); } #endif if (error) { printf("revarp failed, error=%d\n", error); goto out; } if (!(*flags & NFS_BOOT_HAS_MYIP)) { nd->nd_myip.s_addr = my_ip.s_addr; printf("nfs_boot: client_addr=%s", inet_ntoa(my_ip)); printf(" (RARP from %s)\n", inet_ntoa(arps_ip)); *flags |= NFS_BOOT_HAS_MYIP; } /* * Do enough of ifconfig(8) so that the chosen interface * can talk to the servers. (just set the address) */ error = nfs_boot_setaddress(ifp, lwp, my_ip.s_addr, INADDR_ANY, INADDR_ANY); if (error) { printf("nfs_boot: set ifaddr, error=%d\n", error); goto out; } /* * Get client name and gateway address. * RPC: bootparam/whoami * Use the old broadcast address for the WHOAMI * call because we do not yet know our netmask. * The server address returned by the WHOAMI call * is used for all subsequent booptaram RPCs. */ sin = &bp_sin; memset((void *)sin, 0, sizeof(*sin)); sin->sin_len = sizeof(*sin); sin->sin_family = AF_INET; sin->sin_addr.s_addr = INADDR_BROADCAST; /* Do the RPC/bootparam/whoami. */ error = bp_whoami(sin, &my_ip, &gw_ip, lwp); if (error) { printf("nfs_boot: bootparam whoami, error=%d\n", error); goto delout; } *flags |= NFS_BOOT_HAS_SERVADDR | NFS_BOOT_HAS_SERVER; printf("nfs_boot: server_addr=%s\n", inet_ntoa(sin->sin_addr)); printf("nfs_boot: hostname=%s\n", hostname); /* * Now fetch the server:pathname strings and server IP * for root and swap. Missing swap is not fatal. */ error = bp_getfile(sin, "root", &nd->nd_root, lwp); if (error) { printf("nfs_boot: bootparam get root: %d\n", error); goto delout; } *flags |= NFS_BOOT_HAS_ROOTPATH; #ifndef NFS_BOOTPARAM_NOGATEWAY gw_ndm = kmem_alloc(sizeof(*gw_ndm), KM_SLEEP); memset((void *)gw_ndm, 0, sizeof(*gw_ndm)); error = bp_getfile(sin, "gateway", gw_ndm, lwp); if (error) { /* No gateway supplied. No error, but try fallback. */ error = 0; goto nogwrepl; } sin = (struct sockaddr_in *) &gw_ndm->ndm_saddr; if (sin->sin_addr.s_addr == 0) goto out; /* no gateway */ /* OK, we have a gateway! */ printf("nfs_boot: gateway=%s\n", inet_ntoa(sin->sin_addr)); /* Just save it. Caller adds the route. */ nd->nd_gwip = sin->sin_addr; *flags |= NFS_BOOT_HAS_GWIP; /* Look for a mask string after the colon. */ p = strchr(gw_ndm->ndm_host, ':'); if (p == 0) goto out; /* no netmask */ /* have pathname */ p++; /* skip ':' */ mask = inet_addr(p); /* libkern */ if (mask == 0) goto out; /* no netmask */ /* Have a netmask too! Save it; update the I/F. */ nd->nd_mask.s_addr = mask; *flags |= NFS_BOOT_HAS_MASK; printf("nfs_boot: my_mask=%s\n", inet_ntoa(nd->nd_mask)); (void) nfs_boot_deladdress(ifp, lwp, my_ip.s_addr); error = nfs_boot_setaddress(ifp, lwp, my_ip.s_addr, mask, INADDR_ANY); if (error) { printf("nfs_boot: set ifmask, error=%d\n", error); goto out; } goto gwok; nogwrepl: #endif #ifdef NFS_BOOT_GATEWAY /* * Note: we normally ignore the gateway address returned * by the "bootparam/whoami" RPC above, because many old * bootparam servers supply a bogus gateway value. * * These deficiencies in the bootparam RPC interface are * circumvented by using the bootparam/getfile RPC. The * parameter "gateway" is requested, and if its returned, * we use the "server" part of the reply as the gateway, * and use the "pathname" part of the reply as the mask. * (The mask comes to us as a string.) */ if (gw_ip.s_addr) { /* Our caller will add the route. */ nd->nd_gwip = gw_ip; *flags |= NFS_BOOT_HAS_GWIP; } #endif delout: if (error) (void) nfs_boot_deladdress(ifp, lwp, my_ip.s_addr); out: if (error) { (void) nfs_boot_ifupdown(ifp, lwp, 0); nfs_boot_flushrt(ifp); } #ifndef NFS_BOOTPARAM_NOGATEWAY gwok: if (gw_ndm) kmem_free(gw_ndm, sizeof(*gw_ndm)); #endif if ((*flags & NFS_BOOT_ALLINFO) != NFS_BOOT_ALLINFO) return error ? error : EADDRNOTAVAIL; return (error); }