int net_mountroot(void) { #ifdef DEBUG printf("net_mountroot\n"); #endif /* * Get info for NFS boot: our IP address, our hostname, * server IP address, and our root path on the server. * There are two ways to do this: The old, Sun way, * and the more modern, BOOTP way. (RFC951, RFC1048) */ #ifdef SUN_BOOTPARAMS /* Get boot info using RARP and Sun bootparams. */ /* Get our IP address. (rarp.c) */ if (rarp_getipaddress(netdev_sock) == -1) return errno; printf("boot: client IP address: %s\n", inet_ntoa(myip)); /* Get our hostname, server IP address. */ if (bp_whoami(netdev_sock)) return (errno); printf("boot: client name: %s\n", hostname); /* Get the root pathname. */ if (bp_getfile(netdev_sock, "root", &rootip, rootpath)) return (errno); #else /* Get boot info using BOOTP way. (RFC951, RFC1048) */ bootp(netdev_sock); printf("Using IP address: %s\n", inet_ntoa(myip)); printf("myip: %s (%s)", hostname, inet_ntoa(myip)); if (gateip) printf(", gateip: %s", inet_ntoa(gateip)); if (netmask) printf(", netmask: %s", intoa(netmask)); printf("\n"); #endif printf("root addr=%s path=%s\n", inet_ntoa(rootip), rootpath); /* Get the NFS file handle (mount). */ if (nfs_mount(netdev_sock, rootip, rootpath) != 0) return (errno); return 0; }
int net_mountroot_bootparams(void) { /* Get our IP address. (rarp.c) */ if (rarp_getipaddress(netdev_sock) == -1) return (errno); printf("Using BOOTPARAMS protocol: "); printf("ip address: %s", inet_ntoa(myip)); /* Get our hostname, server IP address. */ if (bp_whoami(netdev_sock)) return (errno); printf(", hostname: %s\n", hostname); /* Get the root pathname. */ if (bp_getfile(netdev_sock, "root", &rootip, rootpath)) return (errno); return (0); }
static int net_getparams(int sock) { char buf[MAXHOSTNAMELEN]; n_long rootaddr, smask; #ifdef SUPPORT_BOOTP /* * Try to get boot info using BOOTP. If we succeed, then * the server IP address, gateway, and root path will all * be initialized. If any remain uninitialized, we will * use RARP and RPC/bootparam (the Sun way) to get them. */ if (try_bootp) bootp(sock, BOOTP_NONE); if (myip.s_addr != 0) goto exit; #ifdef NETIF_DEBUG if (debug) printf("net_open: BOOTP failed, trying RARP/RPC...\n"); #endif #endif /* * Use RARP to get our IP address. This also sets our * netmask to the "natural" default for our address. */ if (rarp_getipaddress(sock)) { printf("net_open: RARP failed\n"); return (EIO); } printf("net_open: client addr: %s\n", inet_ntoa(myip)); /* Get our hostname, server IP address, gateway. */ if (bp_whoami(sock)) { printf("net_open: bootparam/whoami RPC failed\n"); return (EIO); } #ifdef NETIF_DEBUG if (debug) printf("net_open: client name: %s\n", hostname); #endif /* * Ignore the gateway from whoami (unreliable). * Use the "gateway" parameter instead. */ smask = 0; gateip.s_addr = 0; if (bp_getfile(sock, "gateway", &gateip, buf) == 0) { /* Got it! Parse the netmask. */ smask = ip_convertaddr(buf); } if (smask) { netmask = smask; #ifdef NETIF_DEBUG if (debug) printf("net_open: subnet mask: %s\n", intoa(netmask)); #endif } #ifdef NETIF_DEBUG if (gateip.s_addr && debug) printf("net_open: net gateway: %s\n", inet_ntoa(gateip)); #endif /* Get the root server and pathname. */ if (bp_getfile(sock, "root", &rootip, rootpath)) { printf("net_open: bootparam/getfile RPC failed\n"); return (EIO); } exit: if ((rootaddr = net_parse_rootpath()) != INADDR_NONE) rootip.s_addr = rootaddr; #ifdef NETIF_DEBUG if (debug) { printf("net_open: server addr: %s\n", inet_ntoa(rootip)); printf("net_open: server path: %s\n", rootpath); } #endif return (0); }
int netmountroot(struct open_file *f, char *devname) { int error; struct iodesc *d; #ifdef DEBUG printf("netmountroot: %s\n", devname); #endif if (netio_ask) { get_my_ip: printf("My IP address? "); bzero(input_line, sizeof(input_line)); gets(input_line); if ((myip.s_addr = inet_addr(input_line)) == htonl(INADDR_NONE)) { printf("invalid IP address: %s\n", input_line); goto get_my_ip; } get_my_netmask: printf("My netmask? "); bzero(input_line, sizeof(input_line)); gets(input_line); if ((netmask = inet_addr(input_line)) == htonl(INADDR_NONE)) { printf("invalid netmask: %s\n", input_line); goto get_my_netmask; } get_my_gateway: printf("My gateway? "); bzero(input_line, sizeof(input_line)); gets(input_line); if ((gateip.s_addr = inet_addr(input_line)) == htonl(INADDR_NONE)) { printf("invalid IP address: %s\n", input_line); goto get_my_gateway; } get_server_ip: printf("Server IP address? "); bzero(input_line, sizeof(input_line)); gets(input_line); if ((rootip.s_addr = inet_addr(input_line)) == htonl(INADDR_NONE)) { printf("invalid IP address: %s\n", input_line); goto get_server_ip; } get_server_path: printf("Server path? "); bzero(rootpath, sizeof(rootpath)); gets(rootpath); if (rootpath[0] == '\0' || rootpath[0] == '\n') goto get_server_path; if ((d = socktodesc(netdev_sock)) == NULL) return (EMFILE); d->myip = myip; goto do_nfs_mount; } /* * Get info for NFS boot: our IP address, our hostname, * server IP address, and our root path on the server. * There are two ways to do this: The old, Sun way, * and the more modern, BOOTP way. (RFC951, RFC1048) */ #ifdef SUN_BOOTPARAMS /* Get boot info using RARP and Sun bootparams. */ /* Get our IP address. (rarp.c) */ if (rarp_getipaddress(netdev_sock) == -1) return (errno); printf("boot: client IP address: %s\n", inet_ntoa(myip)); /* Get our hostname, server IP address. */ if (bp_whoami(netdev_sock)) return (errno); printf("boot: client name: %s\n", hostname); /* Get the root pathname. */ if (bp_getfile(netdev_sock, "root", &rootip, rootpath)) return (errno); #else /* Get boot info using BOOTP way. (RFC951, RFC1048) */ bootp(netdev_sock); printf("Using IP address: %s\n", inet_ntoa(myip)); printf("myip: %s (%s)", hostname, inet_ntoa(myip)); if (gateip) printf(", gateip: %s", inet_ntoa(gateip)); if (mask) printf(", mask: %s", intoa(netmask)); printf("\n"); #endif /* SUN_BOOTPARAMS */ printf("root addr=%s path=%s\n", inet_ntoa(rootip), rootpath); do_nfs_mount: /* Get the NFS file handle (mount). */ error = nfs_mount(netdev_sock, rootip, rootpath); return (error); }
/* * 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); }
static int net_getparams(int sock) { char buf[MAXHOSTNAMELEN]; char temp[FNAME_SIZE]; struct iodesc *d; int i; n_long smask; #ifdef SUPPORT_BOOTP /* * Try to get boot info using BOOTP. If we succeed, then * the server IP address, gateway, and root path will all * be initialized. If any remain uninitialized, we will * use RARP and RPC/bootparam (the Sun way) to get them. */ if (try_bootp) bootp(sock, BOOTP_NONE); if (myip.s_addr != 0) goto exit; if (debug) printf("net_open: BOOTP failed, trying RARP/RPC...\n"); #endif /* * Use RARP to get our IP address. This also sets our * netmask to the "natural" default for our address. */ if (rarp_getipaddress(sock)) { printf("net_open: RARP failed\n"); return (EIO); } printf("net_open: client addr: %s\n", inet_ntoa(myip)); /* Get our hostname, server IP address, gateway. */ if (bp_whoami(sock)) { printf("net_open: bootparam/whoami RPC failed\n"); return (EIO); } printf("net_open: client name: %s\n", hostname); /* * Ignore the gateway from whoami (unreliable). * Use the "gateway" parameter instead. */ smask = 0; gateip.s_addr = 0; if (bp_getfile(sock, "gateway", &gateip, buf) == 0) { /* Got it! Parse the netmask. */ smask = ip_convertaddr(buf); } if (smask) { netmask = smask; printf("net_open: subnet mask: %s\n", intoa(netmask)); } if (gateip.s_addr) printf("net_open: net gateway: %s\n", inet_ntoa(gateip)); /* Get the root server and pathname. */ if (bp_getfile(sock, "root", &rootip, rootpath)) { printf("net_open: bootparam/getfile RPC failed\n"); return (EIO); } exit: /* * If present, strip the server's address off of the rootpath * before passing it along. This allows us to be compatible with * the kernel's diskless (BOOTP_NFSROOT) booting conventions */ for (i = 0; i < FNAME_SIZE && rootpath[i] != '\0'; i++) if (rootpath[i] == ':') break; if (i && i != FNAME_SIZE && rootpath[i] == ':') { rootpath[i++] = '\0'; if (inet_addr(&rootpath[0]) != INADDR_NONE) rootip.s_addr = inet_addr(&rootpath[0]); memcpy(&temp[0], &rootpath[i], strlen(&rootpath[i])+1); memcpy(&rootpath[0], &temp[0], strlen(&rootpath[i])+1); } printf("net_open: server addr: %s\n", inet_ntoa(rootip)); printf("net_open: server path: %s\n", rootpath); d = socktodesc(sock); snprintf(temp, sizeof(temp), "%6D", d->myea, ":"); setenv("boot.netif.ip", inet_ntoa(myip), 1); setenv("boot.netif.netmask", intoa(netmask), 1); setenv("boot.netif.gateway", inet_ntoa(gateip), 1); setenv("boot.netif.hwaddr", temp, 1); setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); setenv("boot.nfsroot.path", rootpath, 1); return (0); }
int net_devinit(struct open_file *f, struct netif_driver *drv, u_char *eaddr) { static struct netif best_if; struct iodesc *s; int r; if (inited) return 0; /* find a free socket */ s = &desc; memset(s, 0, sizeof(*s)); best_if.nif_driver = drv; s->io_netif = &best_if; memcpy(s->myea, eaddr, 6); /* * Get info for NFS boot: our IP address, our hostname, * server IP address, and our root path on the server. * There are two ways to do this: The old, Sun way, * and the more modern, BOOTP way. (RFC951, RFC1048) */ #ifdef SUPPORT_BOOTP /* Get boot info using BOOTP way. (RFC951, RFC1048) */ printf("Trying BOOTP\n"); bootp(0); if (myip.s_addr) { printf("Using IP address: %s\n", inet_ntoa(myip)); printf("myip: %s (%s)\n", hostname, inet_ntoa(myip)); } else #endif /* SUPPORT_BOOTP */ { #ifdef SUPPORT_BOOTPARAMS /* Get boot info using RARP and Sun bootparams. */ printf("Trying BOOTPARAMS\n"); /* Get our IP address. (rarp.c) */ if (rarp_getipaddress(0) == -1) return (errno); printf("boot: client IP address: %s\n", inet_ntoa(myip)); /* Get our hostname, server IP address. */ if (bp_whoami(0)) return (errno); printf("boot: client name: %s\n", hostname); /* Get the root pathname. */ if (bp_getfile(0, "root", &rootip, rootpath)) return (errno); #endif } printf("root addr=%s path=%s\n", inet_ntoa(rootip), rootpath); f->f_devdata = s; /* Get the NFS file handle (mount). */ r = nfs_mount(0, rootip, rootpath); if (r) return r; inited = 1; return 0; }
/* * Called by devopen after it sets f->f_dev to our devsw entry. * This opens the low-level device and sets f->f_devdata. */ int net_open(struct open_file *f, ...) { int error = 0; #ifdef NET_DEBUG if (netdev_sock != -1) panic("net_open"); #endif /* Find network interface. */ if ((netdev_sock = netif_open()) < 0) return (ENXIO); #ifdef SUPPORT_BOOTP printf("configure network...trying bootp\n"); /* Get boot info using BOOTP way. (RFC951, RFC1048) */ bootp(netdev_sock); #endif if (myip.s_addr != INADDR_ANY) { /* got bootp reply or * manually set */ #ifdef TFTP_HACK int num, i; /* XXX (some) tftp servers don't like leading "/" */ for (num = 0; bootfile[num] == '/'; num++); for (i = 0; (bootfile[i] = bootfile[i + num]) != 0; i++); #endif printf("boot: client IP address: %s\n", inet_ntoa(myip)); printf("boot: client name: %s\n", hostname); } else { #ifdef SUPPORT_RARP /* * no answer, Get boot info using RARP and Sun * bootparams. */ printf("configure network...trying rarp\n"); /* Get our IP address. (rarp.c) */ if (rarp_getipaddress(netdev_sock)) { error = EIO; goto bad; } printf("boot: client IP address: %s\n", inet_ntoa(myip)); #ifdef SUPPORT_BOOTPARAM /* Get our hostname, server IP address. */ if (!bp_whoami(netdev_sock)) { printf("boot: client name: %s\n", hostname); /* Get the root pathname. */ bp_getfile(netdev_sock, "root", &rootip, rootpath); } #else /* * else fallback: use rarp server address */ #endif #else /* no SUPPORT_RARP */ error = EIO; goto bad; #endif } printf("boot: server: %s, rootpath: %s, bootfile: %s\n", inet_ntoa(rootip), rootpath, bootfile); f->f_devdata = &netdev_sock; return (error); bad: printf("net_open failed\n"); netif_close(netdev_sock); return (error); }
/* * Called with an empty nfs_diskless struct to be filled in. */ int nfs_boot_init(struct nfs_diskless *nd) { struct sockaddr_in bp_sin; boolean_t do_bpwhoami = TRUE; boolean_t do_bpgetfile = TRUE; int error = 0; struct in_addr my_ip; struct sockaddr_in * sin_p; /* make sure mbuf constants are set up */ if (!nfs_mbuf_mhlen) nfs_mbuf_init(); /* by this point, networking must already have been configured */ if (netboot_iaddr(&my_ip) == FALSE) { printf("nfs_boot: networking is not initialized\n"); error = ENXIO; goto failed; } /* get the root path information */ MALLOC_ZONE(nd->nd_root.ndm_path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); if (!nd->nd_root.ndm_path) { printf("nfs_boot: can't allocate root path buffer\n"); error = ENOMEM; goto failed; } MALLOC_ZONE(nd->nd_root.ndm_mntfrom, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); if (!nd->nd_root.ndm_mntfrom) { printf("nfs_boot: can't allocate root mntfrom buffer\n"); error = ENOMEM; goto failed; } sin_p = &nd->nd_root.ndm_saddr; bzero((caddr_t)sin_p, sizeof(*sin_p)); sin_p->sin_len = sizeof(*sin_p); sin_p->sin_family = AF_INET; if (netboot_rootpath(&sin_p->sin_addr, nd->nd_root.ndm_host, sizeof(nd->nd_root.ndm_host), nd->nd_root.ndm_path, MAXPATHLEN) == TRUE) { do_bpgetfile = FALSE; do_bpwhoami = FALSE; } nd->nd_private.ndm_saddr.sin_addr.s_addr = 0; if (do_bpwhoami) { struct in_addr router; /* * 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. */ bzero((caddr_t)&bp_sin, sizeof(bp_sin)); bp_sin.sin_len = sizeof(bp_sin); bp_sin.sin_family = AF_INET; bp_sin.sin_addr.s_addr = INADDR_BROADCAST; hostnamelen = MAXHOSTNAMELEN; router.s_addr = 0; error = bp_whoami(&bp_sin, &my_ip, &router); if (error) { printf("nfs_boot: bootparam whoami, error=%d", error); goto failed; } printf("nfs_boot: BOOTPARAMS server " IP_FORMAT "\n", IP_LIST(&bp_sin.sin_addr)); printf("nfs_boot: hostname %s\n", hostname); } if (do_bpgetfile) { error = bp_getfile(&bp_sin, "root", &nd->nd_root.ndm_saddr, nd->nd_root.ndm_host, nd->nd_root.ndm_path); if (error) { printf("nfs_boot: bootparam get root: %d\n", error); goto failed; } } #if !defined(NO_MOUNT_PRIVATE) if (do_bpgetfile) { /* get private path */ MALLOC_ZONE(nd->nd_private.ndm_path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); if (!nd->nd_private.ndm_path) { printf("nfs_boot: can't allocate private path buffer\n"); error = ENOMEM; goto failed; } MALLOC_ZONE(nd->nd_private.ndm_mntfrom, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); if (!nd->nd_private.ndm_mntfrom) { printf("nfs_boot: can't allocate private host buffer\n"); error = ENOMEM; goto failed; } error = bp_getfile(&bp_sin, "private", &nd->nd_private.ndm_saddr, nd->nd_private.ndm_host, nd->nd_private.ndm_path); if (!error) { char * check_path = NULL; MALLOC_ZONE(check_path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); if (!check_path) { printf("nfs_boot: can't allocate check_path buffer\n"); error = ENOMEM; goto failed; } snprintf(check_path, MAXPATHLEN, "%s/private", nd->nd_root.ndm_path); if ((nd->nd_root.ndm_saddr.sin_addr.s_addr == nd->nd_private.ndm_saddr.sin_addr.s_addr) && (strncmp(check_path, nd->nd_private.ndm_path, MAXPATHLEN) == 0)) { /* private path is prefix of root path, don't mount */ nd->nd_private.ndm_saddr.sin_addr.s_addr = 0; } FREE_ZONE(check_path, MAXPATHLEN, M_NAMEI); } else { /* private key not defined, don't mount */ nd->nd_private.ndm_saddr.sin_addr.s_addr = 0; } } else {