Index: sys/boot/common/dev_net.c =================================================================== RCS file: /home/ncvs/src/sys/boot/common/dev_net.c,v retrieving revision 1.10 diff -u -r1.10 dev_net.c --- sys/boot/common/dev_net.c 10 Nov 2000 06:37:43 -0000 1.10 +++ sys/boot/common/dev_net.c 31 Jul 2002 16:33:52 -0000 @@ -209,6 +209,7 @@ { char buf[MAXHOSTNAMELEN]; char temp[FNAME_SIZE]; + struct iodesc *d; int i; n_long smask; @@ -284,6 +285,14 @@ bcopy(&temp[0], &rootpath[0], strlen(&rootpath[i])+1); } printf("net_open: server path: %s\n", rootpath); + + d = socktodesc(sock); + sprintf(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); + return (0); } Index: sys/conf/files =================================================================== RCS file: /home/ncvs/src/sys/conf/files,v retrieving revision 1.674 diff -u -r1.674 files --- sys/conf/files 24 Jul 2002 12:43:27 -0000 1.674 +++ sys/conf/files 31 Jul 2002 16:33:53 -0000 @@ -981,6 +981,7 @@ libkern/iconv_converter_if.m optional libiconv libkern/iconv_xlat.c optional libiconv libkern/index.c standard +libkern/inet_aton.c standard libkern/inet_ntoa.c standard libkern/mcount.c optional profiling-routine libkern/qsort.c standard @@ -1281,6 +1282,7 @@ nfsclient/bootp_subr.c optional bootp nfsclient nfsclient/krpc_subr.c optional bootp nfsclient nfsclient/nfs_bio.c optional nfsclient +nfsclient/nfs_diskless.c optional nfsclient nfs_root nfsclient/nfs_node.c optional nfsclient nfsclient/nfs_socket.c optional nfsclient nfsclient/nfs_subs.c optional nfsclient Index: sys/libkern/inet_aton.c =================================================================== RCS file: sys/libkern/inet_aton.c diff -N sys/libkern/inet_aton.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/libkern/inet_aton.c 31 Jul 2002 16:33:59 -0000 @@ -0,0 +1,169 @@ +/* $KAME: inet_addr.c,v 1.5 2001/08/20 02:32:40 itojun Exp $ */ + +/* + * ++Copyright++ 1983, 1990, 1993 + * - + * Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * - + * --Copyright-- + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; +#endif /* LIBC_SCCS and not lint */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include + +/* + * Check whether "cp" is a valid ASCII representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int +inet_aton(cp, addr) + const char *cp; + struct in_addr *addr; +{ + u_long parts[4]; + in_addr_t val; + const char *c; + char *endptr; + int gotend, n; + + c = cp; + n = 0; + /* + * Run through the string, grabbing numbers until + * the end of the string, or some error + */ + gotend = 0; + while (!gotend) { + val = strtoul(c, &endptr, 0); + + /* + * If the whole string is invalid, endptr will equal + * c.. this way we can make sure someone hasn't + * gone '.12' or something which would get past + * the next check. + */ + if (endptr == c) + return (0); + parts[n] = val; + c = endptr; + + /* Check the next character past the previous number's end */ + switch (*c) { + case '.' : + /* Make sure we only do 3 dots .. */ + if (n == 3) /* Whoops. Quit. */ + return (0); + n++; + c++; + break; + + case '\0': + gotend = 1; + break; + + default: + if (isspace((unsigned char)*c)) { + gotend = 1; + break; + } else + return (0); /* Invalid character, so fail */ + } + + } + + /* + * Concoct the address according to + * the number of parts specified. + */ + + switch (n) { + case 0: /* a -- 32 bits */ + /* + * Nothing is necessary here. Overflow checking was + * already done in strtoul(). + */ + break; + case 1: /* a.b -- 8.24 bits */ + if (val > 0xffffff || parts[0] > 0xff) + return (0); + val |= parts[0] << 24; + break; + + case 2: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff || parts[0] > 0xff || parts[1] > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 3: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff || parts[0] > 0xff || parts[1] > 0xff || + parts[2] > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + + if (addr != NULL) + addr->s_addr = htonl(val); + return (1); +} Index: sys/netinet/in.h =================================================================== RCS file: /home/ncvs/src/sys/netinet/in.h,v retrieving revision 1.69 diff -u -r1.69 in.h --- sys/netinet/in.h 11 May 2002 23:28:51 -0000 1.69 +++ sys/netinet/in.h 31 Jul 2002 16:34:01 -0000 @@ -531,6 +531,7 @@ int in_broadcast(struct in_addr, struct ifnet *); int in_canforward(struct in_addr); int in_localaddr(struct in_addr); +int inet_aton(const char *cp, struct in_addr *addr); /* in libkern */ char *inet_ntoa(struct in_addr); /* in libkern */ char *inet_ntoa_r(struct in_addr ina, char *buf); /* in libkern */ Index: sys/nfsclient/nfs_diskless.c =================================================================== RCS file: sys/nfsclient/nfs_diskless.c diff -N sys/nfsclient/nfs_diskless.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/nfsclient/nfs_diskless.c 31 Jul 2002 16:34:01 -0000 @@ -0,0 +1,230 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void nfs_diskless_setup(void *arg); +static int inaddr_to_sockaddr(char *ev, struct sockaddr_in *sa); +static int hwaddr_to_sockaddr(char *ev, struct sockaddr_dl *sa); +static int decode_nfshandle(char *ev, u_char *fh); + +SYSINIT(nfs_diskless, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, nfs_diskless_setup, + NULL) + +/* + * Populate the essential fields in the nfsv3_diskless structure. + * + * The loader is expected to export the following environment variables: + * + * boot.netif.ip IP address on boot interface + * boot.netif.netmask netmask on boot interface + * boot.netif.gateway default gateway (optional) + * boot.netif.hwaddr hardware address of boot interface + * boot.nfsroot.server IP address of root filesystem server + * boot.nfsroot.path path of the root filesystem on server + * boot.nfsroot.nfshandle NFS handle for root filesystem on server + */ +static void +nfs_diskless_setup(void *arg) +{ + struct nfs_diskless *nd = &nfs_diskless; + struct ifnet *ifp; + struct ifaddr *ifa; + struct sockaddr_dl *sdl, ourdl; + struct sockaddr_in myaddr, netmask; + char *cp; + + /* set up interface */ + if (inaddr_to_sockaddr("boot.netif.ip", &myaddr)) + return; + if (inaddr_to_sockaddr("boot.netif.netmask", &netmask)) { + printf("nfs_diskless: no netmask\n"); + return; + } + bcopy(&myaddr, &nd->myif.ifra_addr, sizeof(myaddr)); + bcopy(&myaddr, &nd->myif.ifra_broadaddr, sizeof(myaddr)); + ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = + myaddr.sin_addr.s_addr | ~ netmask.sin_addr.s_addr; + bcopy(&netmask, &nd->myif.ifra_mask, sizeof(netmask)); + + if (hwaddr_to_sockaddr("boot.netif.hwaddr", &ourdl)) { + printf("nfs_diskless: no hardware address\n"); + return; + } + ifa = NULL; + TAILQ_FOREACH(ifp, &ifnet, if_link) { + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + if ((ifa->ifa_addr->sa_family == AF_LINK) && + (sdl = ((struct sockaddr_dl *)ifa->ifa_addr))) { + if ((sdl->sdl_type == ourdl.sdl_type) && + (sdl->sdl_alen == ourdl.sdl_alen) && + !bcmp(sdl->sdl_data + sdl->sdl_nlen, + ourdl.sdl_data + ourdl.sdl_nlen, + sdl->sdl_alen)) + goto match_done; + } + } + } + printf("nfs_diskless: no interface\n"); + return; /* no matching interface */ +match_done: + sprintf(nd->myif.ifra_name, "%s%d", ifp->if_name, ifp->if_unit); + + /* set up gateway */ + inaddr_to_sockaddr("boot.netif.gateway", &nd->mygateway); + + /* XXX set up swap? */ + + /* set up root mount */ + nd->root_args.rsize = 8192; /* XXX tunable? */ + nd->root_args.wsize = 8192; + nd->root_args.sotype = SOCK_DGRAM; + nd->root_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | NFSMNT_RESVPORT); + if (inaddr_to_sockaddr("boot.nfsroot.server", &nd->root_saddr)) { + printf("nfs_diskless: no server\n"); + return; + } + nd->root_saddr.sin_port = htons(NFS_PORT); + if (decode_nfshandle("boot.nfsroot.nfshandle", &nd->root_fh[0]) == 0) { + printf("nfs_diskless: no NFS handle\n"); + return; + } + if ((cp = getenv("boot.nfsroot.path")) != NULL) { + strncpy(nd->root_hostnam, cp, MNAMELEN - 1); + freeenv(cp); + } + + nfs_diskless_valid = 1; + rootdevnames[0] = "nfs:"; +} + +static int +inaddr_to_sockaddr(char *ev, struct sockaddr_in *sa) +{ + char *cp; + int ret; + + bzero(sa, sizeof(*sa)); + sa->sin_len = sizeof(*sa); + sa->sin_family = AF_INET; + + if ((cp = getenv(ev)) == NULL) + return (1); + ret = inet_aton(cp, &sa->sin_addr); + freeenv(cp); + return (ret == 0); +} + +static int +hwaddr_to_sockaddr(char *ev, struct sockaddr_dl *sa) +{ + char *cp; + u_int32_t a[6]; + int count; + + bzero(sa, sizeof(*sa)); + sa->sdl_len = sizeof(*sa); + sa->sdl_family = AF_LINK; + sa->sdl_type = IFT_ETHER; + sa->sdl_alen = ETHER_ADDR_LEN; + if ((cp = getenv(ev)) == NULL) + return (1); + count = sscanf(cp, "%x:%x:%x:%x:%x:%x", + &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]); + freeenv(cp); + if (count != 6) + return (1); + sa->sdl_data[0] = a[0]; + sa->sdl_data[1] = a[1]; + sa->sdl_data[2] = a[2]; + sa->sdl_data[3] = a[3]; + sa->sdl_data[4] = a[4]; + sa->sdl_data[5] = a[5]; + return (0); +} + +static int +decode_nfshandle(char *ev, u_char *fh) +{ + u_char *cp, *ep; + int len, val; + + ep = cp = getenv(ev); + if (cp == NULL) + return (0); + if ((strlen(cp) < 2) || (*cp != 'X')) { + freeenv(ep); + return (0); + } + len = 0; + cp++; + for (;;) { + if (*cp == 'X') { + freeenv(ep); + return (len); + } + if ((sscanf(cp, "%2x", &val) != 1) || (val > 0xff)) { + freeenv(ep); + return (0); + } + *(fh++) = val; + len++; + cp += 2; + if (len > NFSX_V2FH) { + freeenv(ep); + return (0); + } + } +} Index: lib/libstand/nfs.c =================================================================== RCS file: /home/ncvs/src/lib/libstand/nfs.c,v retrieving revision 1.9 diff -u -r1.9 nfs.c --- lib/libstand/nfs.c 7 Jul 2002 23:01:36 -0000 1.9 +++ lib/libstand/nfs.c 31 Jul 2002 16:34:06 -0000 @@ -387,10 +387,14 @@ { struct iodesc *desc; struct nfs_iodesc *currfd; + char buf[2 * NFS_FHSIZE + 3]; + u_char *fh; + char *cp; + int i; #ifndef NFS_NOSYMLINK struct nfs_iodesc *newfd; struct nfsv2_fattrs *fa; - char *cp, *ncp; + char *ncp; int c; char namebuf[NFS_MAXPATHLEN + 1]; char linkbuf[NFS_MAXPATHLEN + 1]; @@ -421,6 +425,16 @@ if ((error = nfs_getrootfh(desc, rootpath, nfs_root_node.fh))) return (error); nfs_root_node.iodesc = desc; + + fh = &nfs_root_node.fh[0]; + buf[0] = 'X'; + cp = &buf[1]; + for (i = 0; i < NFS_FHSIZE; i++, cp += 2) + sprintf(cp, "%02x", fh[i]); + sprintf(cp, "X"); + setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); + setenv("boot.nfsroot.path", rootpath, 1); + setenv("boot.nfsroot.nfshandle", buf, 1); #ifndef NFS_NOSYMLINK /* Fake up attributes for the root dir. */