1*78530d46Smickey /* $OpenBSD: nfs_boot.c,v 1.4 1996/03/31 13:15:34 mickey Exp $ */ 2*78530d46Smickey /* $NetBSD: nfs_boot.c,v 1.25 1996/02/18 11:53:41 fvdl Exp $ */ 3df930be7Sderaadt 4df930be7Sderaadt /* 5df930be7Sderaadt * Copyright (c) 1995 Adam Glass, Gordon Ross 6df930be7Sderaadt * All rights reserved. 7df930be7Sderaadt * 8df930be7Sderaadt * Redistribution and use in source and binary forms, with or without 9df930be7Sderaadt * modification, are permitted provided that the following conditions 10df930be7Sderaadt * are met: 11df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright 12df930be7Sderaadt * notice, this list of conditions and the following disclaimer. 13df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright 14df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the 15df930be7Sderaadt * documentation and/or other materials provided with the distribution. 16df930be7Sderaadt * 3. The name of the authors may not be used to endorse or promote products 17df930be7Sderaadt * derived from this software without specific prior written permission. 18df930be7Sderaadt * 19df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 20df930be7Sderaadt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21df930be7Sderaadt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22df930be7Sderaadt * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23df930be7Sderaadt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24df930be7Sderaadt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25df930be7Sderaadt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26df930be7Sderaadt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27df930be7Sderaadt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28df930be7Sderaadt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29df930be7Sderaadt */ 30df930be7Sderaadt 31df930be7Sderaadt #include <sys/param.h> 32df930be7Sderaadt #include <sys/systm.h> 33df930be7Sderaadt #include <sys/kernel.h> 34df930be7Sderaadt #include <sys/conf.h> 35df930be7Sderaadt #include <sys/ioctl.h> 36df930be7Sderaadt #include <sys/proc.h> 37df930be7Sderaadt #include <sys/mount.h> 38df930be7Sderaadt #include <sys/mbuf.h> 39df930be7Sderaadt #include <sys/reboot.h> 40df930be7Sderaadt #include <sys/socket.h> 41df930be7Sderaadt #include <sys/socketvar.h> 42df930be7Sderaadt 43df930be7Sderaadt #include <net/if.h> 44df930be7Sderaadt #include <net/route.h> 45df930be7Sderaadt 46df930be7Sderaadt #include <netinet/in.h> 47df930be7Sderaadt #include <netinet/if_ether.h> 48df930be7Sderaadt 49df930be7Sderaadt #include <nfs/rpcv2.h> 50*78530d46Smickey #include <nfs/nfsproto.h> 51df930be7Sderaadt #include <nfs/nfs.h> 52df930be7Sderaadt #include <nfs/nfsdiskless.h> 53df930be7Sderaadt #include <nfs/krpc.h> 54df930be7Sderaadt #include <nfs/xdr_subs.h> 55370decb4Sniklas #include <nfs/nfs_var.h> 56df930be7Sderaadt 57df930be7Sderaadt #include "ether.h" 58df930be7Sderaadt #if NETHER == 0 59df930be7Sderaadt 60df930be7Sderaadt int nfs_boot_init(nd, procp) 61df930be7Sderaadt struct nfs_diskless *nd; 62df930be7Sderaadt struct proc *procp; 63df930be7Sderaadt { 64df930be7Sderaadt panic("nfs_boot_init: no ether"); 65df930be7Sderaadt } 66df930be7Sderaadt 67*78530d46Smickey void 68*78530d46Smickey nfs_boot_getfh(bpsin, key, ndmntp) 69*78530d46Smickey struct sockaddr_in *bpsin; 70*78530d46Smickey char *key; 71*78530d46Smickey struct nfs_dlmount *ndmntp; 72*78530d46Smickey { 73*78530d46Smickey /* can not get here */ 74*78530d46Smickey } 75*78530d46Smickey 76df930be7Sderaadt #else /* NETHER */ 77df930be7Sderaadt 78df930be7Sderaadt /* 79df930be7Sderaadt * Support for NFS diskless booting, specifically getting information 80df930be7Sderaadt * about where to boot from, what pathnames, etc. 81df930be7Sderaadt * 82df930be7Sderaadt * This implememtation uses RARP and the bootparam RPC. 83df930be7Sderaadt * We are forced to implement RPC anyway (to get file handles) 84df930be7Sderaadt * so we might as well take advantage of it for bootparam too. 85df930be7Sderaadt * 86df930be7Sderaadt * The diskless boot sequence goes as follows: 87df930be7Sderaadt * (1) Use RARP to get our interface address 88df930be7Sderaadt * (2) Use RPC/bootparam/whoami to get our hostname, 89df930be7Sderaadt * our IP address, and the server's IP address. 90df930be7Sderaadt * (3) Use RPC/bootparam/getfile to get the root path 91df930be7Sderaadt * (4) Use RPC/mountd to get the root file handle 92df930be7Sderaadt * (5) Use RPC/bootparam/getfile to get the swap path 93df930be7Sderaadt * (6) Use RPC/mountd to get the swap file handle 94df930be7Sderaadt * 95df930be7Sderaadt * (This happens to be the way Sun does it too.) 96df930be7Sderaadt */ 97df930be7Sderaadt 98df930be7Sderaadt /* bootparam RPC */ 99df930be7Sderaadt static int bp_whoami __P((struct sockaddr_in *bpsin, 100df930be7Sderaadt struct in_addr *my_ip, struct in_addr *gw_ip)); 101df930be7Sderaadt static int bp_getfile __P((struct sockaddr_in *bpsin, char *key, 102df930be7Sderaadt struct sockaddr_in *mdsin, char *servname, char *path)); 103df930be7Sderaadt 104df930be7Sderaadt /* mountd RPC */ 105df930be7Sderaadt static int md_mount __P((struct sockaddr_in *mdsin, char *path, 106df930be7Sderaadt u_char *fh)); 107df930be7Sderaadt 108df930be7Sderaadt char *nfsbootdevname; 109df930be7Sderaadt 110df930be7Sderaadt /* 111df930be7Sderaadt * Called with an empty nfs_diskless struct to be filled in. 112df930be7Sderaadt */ 113df930be7Sderaadt int 114df930be7Sderaadt nfs_boot_init(nd, procp) 115df930be7Sderaadt struct nfs_diskless *nd; 116df930be7Sderaadt struct proc *procp; 117df930be7Sderaadt { 118df930be7Sderaadt struct ifreq ireq; 119df930be7Sderaadt struct in_addr my_ip, gw_ip; 120df930be7Sderaadt struct sockaddr_in bp_sin; 121df930be7Sderaadt struct sockaddr_in *sin; 122df930be7Sderaadt struct ifnet *ifp; 123df930be7Sderaadt struct socket *so; 124df930be7Sderaadt int error; 125df930be7Sderaadt 126df930be7Sderaadt /* 127df930be7Sderaadt * Find an interface, rarp for its ip address, stuff it, the 128df930be7Sderaadt * implied broadcast addr, and netmask into a nfs_diskless struct. 129df930be7Sderaadt * 130df930be7Sderaadt * This was moved here from nfs_vfsops.c because this procedure 131df930be7Sderaadt * would be quite different if someone decides to write (i.e.) a 132df930be7Sderaadt * BOOTP version of this file (might not use RARP, etc.) 133df930be7Sderaadt */ 134df930be7Sderaadt 135df930be7Sderaadt /* 136df930be7Sderaadt * Find a network interface. 137df930be7Sderaadt */ 138df930be7Sderaadt if (nfsbootdevname) 139df930be7Sderaadt ifp = ifunit(nfsbootdevname); 140df930be7Sderaadt else 141df930be7Sderaadt for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) 142df930be7Sderaadt if ((ifp->if_flags & 143df930be7Sderaadt (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0) 144df930be7Sderaadt break; 145df930be7Sderaadt if (ifp == NULL) 146df930be7Sderaadt panic("nfs_boot: no suitable interface"); 147df930be7Sderaadt sprintf(ireq.ifr_name, "%s%d", ifp->if_name, ifp->if_unit); 148df930be7Sderaadt printf("nfs_boot: using network interface '%s'\n", 149df930be7Sderaadt ireq.ifr_name); 150df930be7Sderaadt 151df930be7Sderaadt /* 152df930be7Sderaadt * Bring up the interface. 153df930be7Sderaadt * 154df930be7Sderaadt * Get the old interface flags and or IFF_UP into them; if 155df930be7Sderaadt * IFF_UP set blindly, interface selection can be clobbered. 156df930be7Sderaadt */ 157df930be7Sderaadt if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0)) != 0) 158df930be7Sderaadt panic("nfs_boot: socreate, error=%d", error); 159df930be7Sderaadt error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)&ireq, procp); 160df930be7Sderaadt if (error) 161df930be7Sderaadt panic("nfs_boot: GIFFLAGS, error=%d", error); 162df930be7Sderaadt ireq.ifr_flags |= IFF_UP; 163df930be7Sderaadt error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)&ireq, procp); 164df930be7Sderaadt if (error) 165df930be7Sderaadt panic("nfs_boot: SIFFLAGS, error=%d", error); 166df930be7Sderaadt 167df930be7Sderaadt /* 168df930be7Sderaadt * Do RARP for the interface address. 169df930be7Sderaadt */ 170df930be7Sderaadt if ((error = revarpwhoami(&my_ip, ifp)) != 0) 171df930be7Sderaadt panic("revarp failed, error=%d", error); 172*78530d46Smickey printf("nfs_boot: client_addr=0x%x\n", (u_int32_t)ntohl(my_ip.s_addr)); 173df930be7Sderaadt 174df930be7Sderaadt /* 175df930be7Sderaadt * Do enough of ifconfig(8) so that the chosen interface 176df930be7Sderaadt * can talk to the servers. (just set the address) 177df930be7Sderaadt */ 178df930be7Sderaadt sin = (struct sockaddr_in *)&ireq.ifr_addr; 179df930be7Sderaadt bzero((caddr_t)sin, sizeof(*sin)); 180df930be7Sderaadt sin->sin_len = sizeof(*sin); 181df930be7Sderaadt sin->sin_family = AF_INET; 182df930be7Sderaadt sin->sin_addr.s_addr = my_ip.s_addr; 183df930be7Sderaadt error = ifioctl(so, SIOCSIFADDR, (caddr_t)&ireq, procp); 184df930be7Sderaadt if (error) 185df930be7Sderaadt panic("nfs_boot: set if addr, error=%d", error); 186df930be7Sderaadt 187df930be7Sderaadt soclose(so); 188df930be7Sderaadt 189df930be7Sderaadt /* 190df930be7Sderaadt * Get client name and gateway address. 191df930be7Sderaadt * RPC: bootparam/whoami 192df930be7Sderaadt * Use the old broadcast address for the WHOAMI 193df930be7Sderaadt * call because we do not yet know our netmask. 194df930be7Sderaadt * The server address returned by the WHOAMI call 195df930be7Sderaadt * is used for all subsequent booptaram RPCs. 196df930be7Sderaadt */ 197df930be7Sderaadt bzero((caddr_t)&bp_sin, sizeof(bp_sin)); 198df930be7Sderaadt bp_sin.sin_len = sizeof(bp_sin); 199df930be7Sderaadt bp_sin.sin_family = AF_INET; 200df930be7Sderaadt bp_sin.sin_addr.s_addr = INADDR_BROADCAST; 201df930be7Sderaadt hostnamelen = MAXHOSTNAMELEN; 202df930be7Sderaadt 203df930be7Sderaadt /* this returns gateway IP address */ 204df930be7Sderaadt error = bp_whoami(&bp_sin, &my_ip, &gw_ip); 205df930be7Sderaadt if (error) 206df930be7Sderaadt panic("nfs_boot: bootparam whoami, error=%d", error); 207df930be7Sderaadt printf("nfs_boot: server_addr=0x%x\n", 208*78530d46Smickey (u_int32_t)ntohl(bp_sin.sin_addr.s_addr)); 209df930be7Sderaadt printf("nfs_boot: hostname=%s\n", hostname); 210df930be7Sderaadt 211df930be7Sderaadt #ifdef NFS_BOOT_GATEWAY 212df930be7Sderaadt /* 213df930be7Sderaadt * XXX - This code is conditionally compiled only because 214df930be7Sderaadt * many bootparam servers (in particular, SunOS 4.1.3) 215df930be7Sderaadt * always set the gateway address to their own address. 216df930be7Sderaadt * The bootparam server is not necessarily the gateway. 217df930be7Sderaadt * We could just believe the server, and at worst you would 218df930be7Sderaadt * need to delete the incorrect default route before adding 219df930be7Sderaadt * the correct one, but for simplicity, ignore the gateway. 220df930be7Sderaadt * If your server is OK, you can turn on this option. 221df930be7Sderaadt * 222df930be7Sderaadt * If the gateway address is set, add a default route. 223df930be7Sderaadt * (The mountd RPCs may go across a gateway.) 224df930be7Sderaadt */ 225df930be7Sderaadt if (gw_ip.s_addr) { 226df930be7Sderaadt struct sockaddr dst, gw, mask; 227df930be7Sderaadt /* Destination: (default) */ 228df930be7Sderaadt bzero((caddr_t)&dst, sizeof(dst)); 229df930be7Sderaadt dst.sa_len = sizeof(dst); 230df930be7Sderaadt dst.sa_family = AF_INET; 231df930be7Sderaadt /* Gateway: */ 232df930be7Sderaadt bzero((caddr_t)&gw, sizeof(gw)); 233df930be7Sderaadt sin = (struct sockaddr_in *)&gw; 234df930be7Sderaadt sin->sin_len = sizeof(gw); 235df930be7Sderaadt sin->sin_family = AF_INET; 236df930be7Sderaadt sin->sin_addr.s_addr = gw_ip.s_addr; 237df930be7Sderaadt /* Mask: (zero length) */ 238df930be7Sderaadt bzero(&mask, sizeof(mask)); 239df930be7Sderaadt 240df930be7Sderaadt printf("nfs_boot: gateway=0x%x\n", ntohl(gw_ip.s_addr)); 241df930be7Sderaadt /* add, dest, gw, mask, flags, 0 */ 242df930be7Sderaadt error = rtrequest(RTM_ADD, &dst, (struct sockaddr *)&gw, 243df930be7Sderaadt &mask, (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL); 244df930be7Sderaadt if (error) 245df930be7Sderaadt printf("nfs_boot: add route, error=%d\n", error); 246df930be7Sderaadt } 247df930be7Sderaadt #endif 248df930be7Sderaadt 249370decb4Sniklas bcopy(&bp_sin, &nd->nd_boot, sizeof(bp_sin)); 250df930be7Sderaadt 251df930be7Sderaadt return (0); 252df930be7Sderaadt } 253df930be7Sderaadt 254370decb4Sniklas void 255370decb4Sniklas nfs_boot_getfh(bpsin, key, ndmntp) 256df930be7Sderaadt struct sockaddr_in *bpsin; /* bootparam server */ 257df930be7Sderaadt char *key; /* root or swap */ 258df930be7Sderaadt struct nfs_dlmount *ndmntp; /* output */ 259df930be7Sderaadt { 260df930be7Sderaadt char pathname[MAXPATHLEN]; 261df930be7Sderaadt char *sp, *dp, *endp; 262370decb4Sniklas struct sockaddr_in *sin; 263df930be7Sderaadt int error; 264df930be7Sderaadt 265370decb4Sniklas sin = &ndmntp->ndm_saddr; 266370decb4Sniklas 267df930be7Sderaadt /* 268df930be7Sderaadt * Get server:pathname for "key" (root or swap) 269df930be7Sderaadt * using RPC to bootparam/getfile 270df930be7Sderaadt */ 271*78530d46Smickey error = bp_getfile(bpsin, key, sin, ndmntp->ndm_host, pathname); 272df930be7Sderaadt if (error) 273df930be7Sderaadt panic("nfs_boot: bootparam get %s: %d", key, error); 274df930be7Sderaadt 275df930be7Sderaadt /* 276df930be7Sderaadt * Get file handle for "key" (root or swap) 277df930be7Sderaadt * using RPC to mountd/mount 278df930be7Sderaadt */ 279370decb4Sniklas error = md_mount(sin, pathname, ndmntp->ndm_fh); 280df930be7Sderaadt if (error) 281df930be7Sderaadt panic("nfs_boot: mountd %s, error=%d", key, error); 282df930be7Sderaadt 283370decb4Sniklas /* Set port number for NFS use. */ 284370decb4Sniklas /* XXX: NFS port is always 2049, right? */ 285370decb4Sniklas error = krpc_portmap(sin, NFS_PROG, NFS_VER2, &sin->sin_port); 286370decb4Sniklas if (error) 287370decb4Sniklas panic("nfs_boot: portmap NFS/v2, error=%d", error); 288370decb4Sniklas 289df930be7Sderaadt /* Construct remote path (for getmntinfo(3)) */ 290df930be7Sderaadt dp = ndmntp->ndm_host; 291df930be7Sderaadt endp = dp + MNAMELEN - 1; 292df930be7Sderaadt dp += strlen(dp); 293df930be7Sderaadt *dp++ = ':'; 294df930be7Sderaadt for (sp = pathname; *sp && dp < endp;) 295df930be7Sderaadt *dp++ = *sp++; 296df930be7Sderaadt *dp = '\0'; 297df930be7Sderaadt 298df930be7Sderaadt } 299df930be7Sderaadt 300df930be7Sderaadt 301df930be7Sderaadt /* 302df930be7Sderaadt * RPC: bootparam/whoami 303df930be7Sderaadt * Given client IP address, get: 304df930be7Sderaadt * client name (hostname) 305df930be7Sderaadt * domain name (domainname) 306df930be7Sderaadt * gateway address 307df930be7Sderaadt * 308df930be7Sderaadt * The hostname and domainname are set here for convenience. 309df930be7Sderaadt * 310df930be7Sderaadt * Note - bpsin is initialized to the broadcast address, 311df930be7Sderaadt * and will be replaced with the bootparam server address 312df930be7Sderaadt * after this call is complete. Have to use PMAP_PROC_CALL 313df930be7Sderaadt * to make sure we get responses only from a servers that 314df930be7Sderaadt * know about us (don't want to broadcast a getport call). 315df930be7Sderaadt */ 316df930be7Sderaadt static int 317df930be7Sderaadt bp_whoami(bpsin, my_ip, gw_ip) 318df930be7Sderaadt struct sockaddr_in *bpsin; 319df930be7Sderaadt struct in_addr *my_ip; 320df930be7Sderaadt struct in_addr *gw_ip; 321df930be7Sderaadt { 322df930be7Sderaadt /* RPC structures for PMAPPROC_CALLIT */ 323df930be7Sderaadt struct whoami_call { 324df930be7Sderaadt u_int32_t call_prog; 325df930be7Sderaadt u_int32_t call_vers; 326df930be7Sderaadt u_int32_t call_proc; 327df930be7Sderaadt u_int32_t call_arglen; 328df930be7Sderaadt } *call; 329df930be7Sderaadt struct callit_reply { 330df930be7Sderaadt u_int32_t port; 331df930be7Sderaadt u_int32_t encap_len; 332df930be7Sderaadt /* encapsulated data here */ 333df930be7Sderaadt } *reply; 334df930be7Sderaadt 335df930be7Sderaadt struct mbuf *m, *from; 336df930be7Sderaadt struct sockaddr_in *sin; 337df930be7Sderaadt int error, msg_len; 338df930be7Sderaadt int16_t port; 339df930be7Sderaadt 340df930be7Sderaadt /* 341df930be7Sderaadt * Build request message for PMAPPROC_CALLIT. 342df930be7Sderaadt */ 343df930be7Sderaadt m = m_get(M_WAIT, MT_DATA); 344df930be7Sderaadt call = mtod(m, struct whoami_call *); 345df930be7Sderaadt m->m_len = sizeof(*call); 346df930be7Sderaadt call->call_prog = txdr_unsigned(BOOTPARAM_PROG); 347df930be7Sderaadt call->call_vers = txdr_unsigned(BOOTPARAM_VERS); 348df930be7Sderaadt call->call_proc = txdr_unsigned(BOOTPARAM_WHOAMI); 349df930be7Sderaadt 350df930be7Sderaadt /* 351df930be7Sderaadt * append encapsulated data (client IP address) 352df930be7Sderaadt */ 353df930be7Sderaadt m->m_next = xdr_inaddr_encode(my_ip); 354df930be7Sderaadt call->call_arglen = txdr_unsigned(m->m_next->m_len); 355df930be7Sderaadt 356df930be7Sderaadt /* RPC: portmap/callit */ 357df930be7Sderaadt bpsin->sin_port = htons(PMAPPORT); 358df930be7Sderaadt from = NULL; 359df930be7Sderaadt error = krpc_call(bpsin, PMAPPROG, PMAPVERS, 360df930be7Sderaadt PMAPPROC_CALLIT, &m, &from); 361df930be7Sderaadt if (error) 362df930be7Sderaadt return error; 363df930be7Sderaadt 364df930be7Sderaadt /* 365df930be7Sderaadt * Parse result message. 366df930be7Sderaadt */ 367df930be7Sderaadt if (m->m_len < sizeof(*reply)) { 368df930be7Sderaadt m = m_pullup(m, sizeof(*reply)); 369df930be7Sderaadt if (m == NULL) 370df930be7Sderaadt goto bad; 371df930be7Sderaadt } 372df930be7Sderaadt reply = mtod(m, struct callit_reply *); 373df930be7Sderaadt port = fxdr_unsigned(u_int32_t, reply->port); 374df930be7Sderaadt msg_len = fxdr_unsigned(u_int32_t, reply->encap_len); 375df930be7Sderaadt m_adj(m, sizeof(*reply)); 376df930be7Sderaadt 377df930be7Sderaadt /* 378df930be7Sderaadt * Save bootparam server address 379df930be7Sderaadt */ 380df930be7Sderaadt sin = mtod(from, struct sockaddr_in *); 381df930be7Sderaadt bpsin->sin_port = htons(port); 382df930be7Sderaadt bpsin->sin_addr.s_addr = sin->sin_addr.s_addr; 383df930be7Sderaadt 384df930be7Sderaadt /* client name */ 385df930be7Sderaadt hostnamelen = MAXHOSTNAMELEN-1; 386df930be7Sderaadt m = xdr_string_decode(m, hostname, &hostnamelen); 387df930be7Sderaadt if (m == NULL) 388df930be7Sderaadt goto bad; 389df930be7Sderaadt 390df930be7Sderaadt /* domain name */ 391df930be7Sderaadt domainnamelen = MAXHOSTNAMELEN-1; 392df930be7Sderaadt m = xdr_string_decode(m, domainname, &domainnamelen); 393df930be7Sderaadt if (m == NULL) 394df930be7Sderaadt goto bad; 395df930be7Sderaadt 396df930be7Sderaadt /* gateway address */ 397df930be7Sderaadt m = xdr_inaddr_decode(m, gw_ip); 398df930be7Sderaadt if (m == NULL) 399df930be7Sderaadt goto bad; 400df930be7Sderaadt 401df930be7Sderaadt /* success */ 402df930be7Sderaadt goto out; 403df930be7Sderaadt 404df930be7Sderaadt bad: 405df930be7Sderaadt printf("nfs_boot: bootparam_whoami: bad reply\n"); 406df930be7Sderaadt error = EBADRPC; 407df930be7Sderaadt 408df930be7Sderaadt out: 409df930be7Sderaadt if (from) 410df930be7Sderaadt m_freem(from); 411df930be7Sderaadt if (m) 412df930be7Sderaadt m_freem(m); 413df930be7Sderaadt return(error); 414df930be7Sderaadt } 415df930be7Sderaadt 416df930be7Sderaadt 417df930be7Sderaadt /* 418df930be7Sderaadt * RPC: bootparam/getfile 419df930be7Sderaadt * Given client name and file "key", get: 420df930be7Sderaadt * server name 421df930be7Sderaadt * server IP address 422df930be7Sderaadt * server pathname 423df930be7Sderaadt */ 424df930be7Sderaadt static int 425df930be7Sderaadt bp_getfile(bpsin, key, md_sin, serv_name, pathname) 426df930be7Sderaadt struct sockaddr_in *bpsin; 427df930be7Sderaadt char *key; 428df930be7Sderaadt struct sockaddr_in *md_sin; 429df930be7Sderaadt char *serv_name; 430df930be7Sderaadt char *pathname; 431df930be7Sderaadt { 432df930be7Sderaadt struct mbuf *m; 433df930be7Sderaadt struct sockaddr_in *sin; 434df930be7Sderaadt struct in_addr inaddr; 435df930be7Sderaadt int error, sn_len, path_len; 436df930be7Sderaadt 437df930be7Sderaadt /* 438df930be7Sderaadt * Build request message. 439df930be7Sderaadt */ 440df930be7Sderaadt 441df930be7Sderaadt /* client name (hostname) */ 442df930be7Sderaadt m = xdr_string_encode(hostname, hostnamelen); 443370decb4Sniklas if (m == NULL) 444370decb4Sniklas return (ENOMEM); 445df930be7Sderaadt 446df930be7Sderaadt /* key name (root or swap) */ 447df930be7Sderaadt m->m_next = xdr_string_encode(key, strlen(key)); 448370decb4Sniklas if (m->m_next == NULL) 449370decb4Sniklas return (ENOMEM); 450df930be7Sderaadt 451df930be7Sderaadt /* RPC: bootparam/getfile */ 452df930be7Sderaadt error = krpc_call(bpsin, BOOTPARAM_PROG, BOOTPARAM_VERS, 453df930be7Sderaadt BOOTPARAM_GETFILE, &m, NULL); 454df930be7Sderaadt if (error) 455df930be7Sderaadt return error; 456df930be7Sderaadt 457df930be7Sderaadt /* 458df930be7Sderaadt * Parse result message. 459df930be7Sderaadt */ 460df930be7Sderaadt 461df930be7Sderaadt /* server name */ 462df930be7Sderaadt sn_len = MNAMELEN-1; 463df930be7Sderaadt m = xdr_string_decode(m, serv_name, &sn_len); 464df930be7Sderaadt if (m == NULL) 465df930be7Sderaadt goto bad; 466df930be7Sderaadt 467df930be7Sderaadt /* server IP address (mountd/NFS) */ 468df930be7Sderaadt m = xdr_inaddr_decode(m, &inaddr); 469df930be7Sderaadt if (m == NULL) 470df930be7Sderaadt goto bad; 471df930be7Sderaadt 472df930be7Sderaadt /* server pathname */ 473df930be7Sderaadt path_len = MAXPATHLEN-1; 474df930be7Sderaadt m = xdr_string_decode(m, pathname, &path_len); 475df930be7Sderaadt if (m == NULL) 476df930be7Sderaadt goto bad; 477df930be7Sderaadt 478df930be7Sderaadt /* setup server socket address */ 479df930be7Sderaadt sin = md_sin; 480df930be7Sderaadt bzero((caddr_t)sin, sizeof(*sin)); 481df930be7Sderaadt sin->sin_len = sizeof(*sin); 482df930be7Sderaadt sin->sin_family = AF_INET; 483df930be7Sderaadt sin->sin_addr = inaddr; 484df930be7Sderaadt 485df930be7Sderaadt /* success */ 486df930be7Sderaadt goto out; 487df930be7Sderaadt 488df930be7Sderaadt bad: 489df930be7Sderaadt printf("nfs_boot: bootparam_getfile: bad reply\n"); 490df930be7Sderaadt error = EBADRPC; 491df930be7Sderaadt 492df930be7Sderaadt out: 493df930be7Sderaadt m_freem(m); 494df930be7Sderaadt return(0); 495df930be7Sderaadt } 496df930be7Sderaadt 497df930be7Sderaadt 498df930be7Sderaadt /* 499df930be7Sderaadt * RPC: mountd/mount 500df930be7Sderaadt * Given a server pathname, get an NFS file handle. 501df930be7Sderaadt * Also, sets sin->sin_port to the NFS service port. 502df930be7Sderaadt */ 503df930be7Sderaadt static int 504df930be7Sderaadt md_mount(mdsin, path, fhp) 505df930be7Sderaadt struct sockaddr_in *mdsin; /* mountd server address */ 506df930be7Sderaadt char *path; 507df930be7Sderaadt u_char *fhp; 508df930be7Sderaadt { 509df930be7Sderaadt /* The RPC structures */ 510df930be7Sderaadt struct rdata { 511df930be7Sderaadt u_int32_t errno; 512*78530d46Smickey u_int8_t fh[NFSX_V2FH]; 513df930be7Sderaadt } *rdata; 514df930be7Sderaadt struct mbuf *m; 515df930be7Sderaadt int error; 516df930be7Sderaadt 517df930be7Sderaadt /* Get port number for MOUNTD. */ 518df930be7Sderaadt error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, 519df930be7Sderaadt &mdsin->sin_port); 520df930be7Sderaadt if (error) return error; 521df930be7Sderaadt 522df930be7Sderaadt m = xdr_string_encode(path, strlen(path)); 523370decb4Sniklas if (m == NULL) 524*78530d46Smickey return ENOMEM; 525df930be7Sderaadt 526df930be7Sderaadt /* Do RPC to mountd. */ 527df930be7Sderaadt error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, 528df930be7Sderaadt RPCMNT_MOUNT, &m, NULL); 529df930be7Sderaadt if (error) 530df930be7Sderaadt return error; /* message already freed */ 531df930be7Sderaadt 532370decb4Sniklas /* The reply might have only the errno. */ 533370decb4Sniklas if (m->m_len < 4) 534370decb4Sniklas goto bad; 535370decb4Sniklas /* Have at least errno, so check that. */ 536370decb4Sniklas rdata = mtod(m, struct rdata *); 537370decb4Sniklas error = fxdr_unsigned(u_int32_t, rdata->errno); 538370decb4Sniklas if (error) 539370decb4Sniklas goto out; 540370decb4Sniklas 541370decb4Sniklas /* Have errno==0, so the fh must be there. */ 542df930be7Sderaadt if (m->m_len < sizeof(*rdata)) { 543df930be7Sderaadt m = m_pullup(m, sizeof(*rdata)); 544df930be7Sderaadt if (m == NULL) 545df930be7Sderaadt goto bad; 546df930be7Sderaadt rdata = mtod(m, struct rdata *); 547370decb4Sniklas } 548*78530d46Smickey bcopy(rdata->fh, fhp, NFSX_V2FH); 549df930be7Sderaadt goto out; 550df930be7Sderaadt 551df930be7Sderaadt bad: 552df930be7Sderaadt error = EBADRPC; 553df930be7Sderaadt 554df930be7Sderaadt out: 555df930be7Sderaadt m_freem(m); 556df930be7Sderaadt return error; 557df930be7Sderaadt } 558df930be7Sderaadt 559df930be7Sderaadt #endif /* NETHER */ 560