|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1995, 1997 NeXT Computer, Inc. All Rights Reserved */ ! 26: /* ! 27: * Copyright (c) 1994 Adam Glass, Gordon Ross ! 28: * All rights reserved. ! 29: * ! 30: * The NEXTSTEP Software License Agreement specifies the terms ! 31: * and conditions for redistribution. ! 32: * ! 33: * History: ! 34: * ! 35: * 14-March-97 Dieter Siegmund ([email protected]) ! 36: * Use BOOTP instead of RARP to get the IP address at boot time ! 37: * ! 38: * 23-May-97 Umesh Vaishampayan ([email protected]) ! 39: * Added the ability to mount "/private" separately. ! 40: * ! 41: * 30-May-97 Dieter Siegmund ([email protected]) ! 42: * - Clear out the ireq structure before using it to prevent ! 43: * our sending using a bogus source IP address, we should use ! 44: * an IP address of all zeroes ! 45: * - Right after BOOTP, get the correct netmask using AUTONETMASK ! 46: * 18-Jul-97 Dieter Siegmund ([email protected]) ! 47: * - we can't restrict the netmask until we have a default route, ! 48: * removed AUTONETMASK call (ifdef'd out) ! 49: * 5-Aug-97 Dieter Siegmund ([email protected]) ! 50: * - use the default route from the bpwhoami call, enabled autonetmask ! 51: * again ! 52: */ ! 53: ! 54: #include <sys/param.h> ! 55: #include <sys/systm.h> ! 56: #include <sys/kernel.h> ! 57: #include <sys/conf.h> ! 58: #include <sys/ioctl.h> ! 59: #include <sys/proc.h> ! 60: #include <sys/mount.h> ! 61: #include <sys/mbuf.h> ! 62: #include <sys/socket.h> ! 63: #include <sys/reboot.h> ! 64: ! 65: #include <net/if.h> ! 66: #include <net/route.h> ! 67: ! 68: #include <netinet/in.h> ! 69: #include <netinet/if_ether.h> ! 70: ! 71: #include <nfs/rpcv2.h> ! 72: #include <nfs/nfsproto.h> ! 73: #include <nfs/nfs.h> ! 74: #include <nfs/nfsdiskless.h> ! 75: #include <nfs/krpc.h> ! 76: ! 77: #include "ether.h" ! 78: ! 79: #if NETHER == 0 ! 80: ! 81: int nfs_boot_init(nd, procp) ! 82: struct nfs_diskless *nd; ! 83: struct proc *procp; ! 84: { ! 85: panic("nfs_boot_init: no ether"); ! 86: } ! 87: ! 88: #else /* NETHER */ ! 89: ! 90: /* ! 91: * Support for NFS diskless booting, specifically getting information ! 92: * about where to boot from, what pathnames, etc. ! 93: * ! 94: * This implememtation uses RARP and the bootparam RPC. ! 95: * We are forced to implement RPC anyway (to get file handles) ! 96: * so we might as well take advantage of it for bootparam too. ! 97: * ! 98: * The diskless boot sequence goes as follows: ! 99: * (1) Use RARP to get our interface address ! 100: * (2) Use RPC/bootparam/whoami to get our hostname, ! 101: * our IP address, and the server's IP address. ! 102: * (3) Use RPC/bootparam/getfile to get the root path ! 103: * (4) Use RPC/mountd to get the root file handle ! 104: * (5) Use RPC/bootparam/getfile to get the swap path ! 105: * (6) Use RPC/mountd to get the swap file handle ! 106: * ! 107: * (This happens to be the way Sun does it too.) ! 108: */ ! 109: ! 110: /* bootparam RPC */ ! 111: static int bp_whoami __P((struct sockaddr_in *bpsin, ! 112: struct in_addr *my_ip, struct in_addr *gw_ip)); ! 113: static int bp_getfile __P((struct sockaddr_in *bpsin, char *key, ! 114: struct sockaddr_in *mdsin, char *servname, char *path)); ! 115: ! 116: /* mountd RPC */ ! 117: static int md_mount __P((struct sockaddr_in *mdsin, char *path, ! 118: u_char *fh)); ! 119: ! 120: /* other helpers */ ! 121: static void get_path_and_handle __P((struct sockaddr_in *bpsin, ! 122: char *key, struct nfs_dlmount *ndmntp)); ! 123: ! 124: char *nfsbootdevname; ! 125: ! 126: /* ! 127: * Called with an empty nfs_diskless struct to be filled in. ! 128: */ ! 129: int ! 130: nfs_boot_init(nd, procp) ! 131: struct nfs_diskless *nd; ! 132: struct proc *procp; ! 133: { ! 134: struct ifreq ireq; ! 135: struct in_addr my_ip, gw_ip; ! 136: struct sockaddr_in bp_sin; ! 137: struct sockaddr_in *sin; ! 138: struct ifnet *ifp; ! 139: struct socket *so; ! 140: int error; ! 141: ! 142: /* clear out the request structure */ ! 143: bzero(&ireq, sizeof(ireq)); ! 144: ! 145: /* ! 146: * Find an interface, rarp for its ip address, stuff it, the ! 147: * implied broadcast addr, and netmask into a nfs_diskless struct. ! 148: * ! 149: * This was moved here from nfs_vfsops.c because this procedure ! 150: * would be quite different if someone decides to write (i.e.) a ! 151: * BOOTP version of this file (might not use RARP, etc.) ! 152: */ ! 153: ! 154: /* ! 155: * Find a network interface. ! 156: */ ! 157: if (nfsbootdevname) ! 158: ifp = ifunit(nfsbootdevname); ! 159: else ! 160: for (ifp = ifnet; ifp; ifp = ifp->if_next) ! 161: if ((ifp->if_flags & ! 162: (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0) ! 163: break; ! 164: if (ifp == NULL) ! 165: panic("nfs_boot: no suitable interface"); ! 166: sprintf(ireq.ifr_name, "%s%d", ifp->if_name, ifp->if_unit); ! 167: printf("nfs_boot: using network interface '%s'\n", ireq.ifr_name); ! 168: ! 169: /* ! 170: * Bring up the interface. ! 171: */ ! 172: if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0)) != 0) ! 173: panic("nfs_boot: socreate, error=%d", error); ! 174: ireq.ifr_flags = IFF_UP; ! 175: error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)&ireq, procp); ! 176: if (error) ! 177: panic("nfs_boot: SIFFLAGS, error=%d", error); ! 178: ! 179: #if NeXT ! 180: /* ! 181: * Do BOOTP to get the interface address ! 182: */ ! 183: { ! 184: int message = 0; ! 185: ! 186: ireq.ifr_addr.sa_family = AF_INET; ! 187: while ((error = ifioctl(so, SIOCAUTOADDR, (caddr_t)&ireq, procp))) { ! 188: if (error == ETIMEDOUT) { ! 189: if (!message) { ! 190: printf("nfs_boot: BOOTP timed out, still trying...\n"); ! 191: message++; ! 192: } ! 193: } ! 194: else { ! 195: printf("nfs_boot: autoaddr failed, error = %d\n", error); ! 196: panic("nfs_boot: SIOCAUTOADDR failed"); ! 197: } ! 198: } ! 199: ! 200: sin = (struct sockaddr_in *)&(ireq.ifr_addr); ! 201: my_ip = sin->sin_addr; ! 202: } ! 203: printf("nfs_boot: client_addr=0x%x\n", ntohl(my_ip.s_addr)); ! 204: ! 205: /* ! 206: * get the netmask ! 207: * XXX - if BOOTP returns a netmask, we should use that instead ! 208: * of icmp (DWS) ! 209: */ ! 210: if ((error = ifioctl(so, SIOCAUTONETMASK, (caddr_t)&ireq, procp))) { ! 211: printf("nfs_boot: autonetmask failed, error = %d\n", error); ! 212: } ! 213: ! 214: #else NeXT ! 215: /* ! 216: * Do RARP for the interface address. ! 217: */ ! 218: if ((error = revarpwhoami(&my_ip, ifp)) != 0) ! 219: panic("revarp failed, error=%d", error); ! 220: printf("nfs_boot: client_addr=0x%x\n", ntohl(my_ip.s_addr)); ! 221: ! 222: /* ! 223: * Do enough of ifconfig(8) so that the chosen interface ! 224: * can talk to the servers. (just set the address) ! 225: */ ! 226: sin = (struct sockaddr_in *)&ireq.ifr_addr; ! 227: bzero((caddr_t)sin, sizeof(*sin)); ! 228: sin->sin_len = sizeof(*sin); ! 229: sin->sin_family = AF_INET; ! 230: sin->sin_addr.s_addr = my_ip.s_addr; ! 231: error = ifioctl(so, SIOCSIFADDR, (caddr_t)&ireq, procp); ! 232: if (error) ! 233: panic("nfs_boot: set if addr, error=%d", error); ! 234: #endif NeXT ! 235: ! 236: soclose(so); ! 237: ! 238: /* ! 239: * Get client name and gateway address. ! 240: * RPC: bootparam/whoami ! 241: * Use the old broadcast address for the WHOAMI ! 242: * call because we do not yet know our netmask. ! 243: * The server address returned by the WHOAMI call ! 244: * is used for all subsequent booptaram RPCs. ! 245: */ ! 246: bzero((caddr_t)&bp_sin, sizeof(bp_sin)); ! 247: bp_sin.sin_len = sizeof(bp_sin); ! 248: bp_sin.sin_family = AF_INET; ! 249: bp_sin.sin_addr.s_addr = INADDR_BROADCAST; ! 250: hostnamelen = MAXHOSTNAMELEN; ! 251: ! 252: /* this returns gateway IP address */ ! 253: error = bp_whoami(&bp_sin, &my_ip, &gw_ip); ! 254: if (error) { ! 255: printf("nfs_boot: bootparam whoami, error=%d", error); ! 256: panic("nfs_boot: bootparam whoami\n"); ! 257: } ! 258: printf("nfs_boot: server_addr=0x%x\n", ! 259: ntohl(bp_sin.sin_addr.s_addr)); ! 260: printf("nfs_boot: hostname=%s\n", hostname); ! 261: #define NFS_BOOT_GATEWAY 1 ! 262: #ifdef NFS_BOOT_GATEWAY ! 263: /* ! 264: * XXX - This code is conditionally compiled only because ! 265: * many bootparam servers (in particular, SunOS 4.1.3) ! 266: * always set the gateway address to their own address. ! 267: * The bootparam server is not necessarily the gateway. ! 268: * We could just believe the server, and at worst you would ! 269: * need to delete the incorrect default route before adding ! 270: * the correct one, but for simplicity, ignore the gateway. ! 271: * If your server is OK, you can turn on this option. ! 272: * ! 273: * If the gateway address is set, add a default route. ! 274: * (The mountd RPCs may go across a gateway.) ! 275: */ ! 276: if (gw_ip.s_addr) { ! 277: struct sockaddr dst, gw, mask; ! 278: /* Destination: (default) */ ! 279: bzero((caddr_t)&dst, sizeof(dst)); ! 280: dst.sa_len = sizeof(dst); ! 281: dst.sa_family = AF_INET; ! 282: /* Gateway: */ ! 283: bzero((caddr_t)&gw, sizeof(gw)); ! 284: sin = (struct sockaddr_in *)&gw; ! 285: sin->sin_len = sizeof(gw); ! 286: sin->sin_family = AF_INET; ! 287: sin->sin_addr.s_addr = gw_ip.s_addr; ! 288: /* Mask: (zero length) */ ! 289: bzero(&mask, sizeof(mask)); ! 290: ! 291: printf("nfs_boot: gateway=0x%x\n", ntohl(gw_ip.s_addr)); ! 292: /* add, dest, gw, mask, flags, 0 */ ! 293: error = rtrequest(RTM_ADD, &dst, (struct sockaddr *)&gw, ! 294: &mask, (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL); ! 295: if (error) ! 296: printf("nfs_boot: add route, error=%d\n", error); ! 297: } ! 298: #endif ! 299: ! 300: get_path_and_handle(&bp_sin, "root", &nd->nd_root); ! 301: #if !defined(NO_MOUNT_PRIVATE) ! 302: get_path_and_handle(&bp_sin, "private", &nd->nd_private); ! 303: #endif /* NO_MOUNT_PRIVATE */ ! 304: ! 305: return (0); ! 306: } ! 307: ! 308: static void ! 309: get_path_and_handle(bpsin, key, ndmntp) ! 310: struct sockaddr_in *bpsin; /* bootparam server */ ! 311: char *key; /* root or swap */ ! 312: struct nfs_dlmount *ndmntp; /* output */ ! 313: { ! 314: char pathname[MAXPATHLEN]; ! 315: char *sp, *dp, *endp; ! 316: int error; ! 317: ! 318: /* ! 319: * Get server:pathname for "key" (root or swap) ! 320: * using RPC to bootparam/getfile ! 321: */ ! 322: error = bp_getfile(bpsin, key, &ndmntp->ndm_saddr, ! 323: ndmntp->ndm_host, pathname); ! 324: if (error) { ! 325: printf("nfs_boot: bootparam get %s: %d\n", key, error); ! 326: panic("nfs_boot: bootparam get %s: %d", key, error); ! 327: } ! 328: /* ! 329: * Get file handle for "key" (root or swap) ! 330: * using RPC to mountd/mount ! 331: */ ! 332: error = md_mount(&ndmntp->ndm_saddr, pathname, ndmntp->ndm_fh); ! 333: if (error) ! 334: panic("nfs_boot: mountd %s, error=%d", key, error); ! 335: ! 336: /* Construct remote path (for getmntinfo(3)) */ ! 337: dp = ndmntp->ndm_host; ! 338: endp = dp + MNAMELEN - 1; ! 339: dp += strlen(dp); ! 340: *dp++ = ':'; ! 341: for (sp = pathname; *sp && dp < endp;) ! 342: *dp++ = *sp++; ! 343: *dp = '\0'; ! 344: ! 345: } ! 346: ! 347: ! 348: /* ! 349: * Get an mbuf with the given length, and ! 350: * initialize the pkthdr length field. ! 351: */ ! 352: static struct mbuf * ! 353: m_get_len(int msg_len) ! 354: { ! 355: struct mbuf *m; ! 356: m = m_gethdr(M_WAIT, MT_DATA); ! 357: if (m == NULL) ! 358: return NULL; ! 359: if (msg_len > MHLEN) { ! 360: if (msg_len > MCLBYTES) ! 361: panic("nfs_boot: msg_len > MCLBYTES"); ! 362: MCLGET(m, M_WAIT); ! 363: if (m == NULL) ! 364: return NULL; ! 365: } ! 366: m->m_len = msg_len; ! 367: m->m_pkthdr.len = m->m_len; ! 368: return (m); ! 369: } ! 370: ! 371: ! 372: /* ! 373: * String representation for RPC. ! 374: */ ! 375: struct rpc_string { ! 376: u_long len; /* length without null or padding */ ! 377: u_char data[4]; /* data (longer, of course) */ ! 378: /* data is padded to a long-word boundary */ ! 379: }; ! 380: /* Compute space used given string length. */ ! 381: #define RPC_STR_SIZE(slen) (4 + ((slen + 3) & ~3)) ! 382: ! 383: /* ! 384: * Inet address in RPC messages ! 385: * (Note, really four longs, NOT chars. Blech.) ! 386: */ ! 387: struct bp_inaddr { ! 388: u_long atype; ! 389: long addr[4]; ! 390: }; ! 391: ! 392: ! 393: /* ! 394: * RPC: bootparam/whoami ! 395: * Given client IP address, get: ! 396: * client name (hostname) ! 397: * domain name (domainname) ! 398: * gateway address ! 399: * ! 400: * The hostname and domainname are set here for convenience. ! 401: * ! 402: * Note - bpsin is initialized to the broadcast address, ! 403: * and will be replaced with the bootparam server address ! 404: * after this call is complete. Have to use PMAP_PROC_CALL ! 405: * to make sure we get responses only from a servers that ! 406: * know about us (don't want to broadcast a getport call). ! 407: */ ! 408: static int ! 409: bp_whoami(bpsin, my_ip, gw_ip) ! 410: struct sockaddr_in *bpsin; ! 411: struct in_addr *my_ip; ! 412: struct in_addr *gw_ip; ! 413: { ! 414: /* RPC structures for PMAPPROC_CALLIT */ ! 415: struct whoami_call { ! 416: u_long call_prog; ! 417: u_long call_vers; ! 418: u_long call_proc; ! 419: u_long call_arglen; ! 420: struct bp_inaddr call_ia; ! 421: } *call; ! 422: ! 423: struct rpc_string *str; ! 424: struct bp_inaddr *bia; ! 425: struct mbuf *m, *from; ! 426: struct sockaddr_in *sin; ! 427: int error, msg_len; ! 428: int cn_len, dn_len; ! 429: u_char *p; ! 430: long *lp; ! 431: ! 432: /* ! 433: * Get message buffer of sufficient size. ! 434: */ ! 435: msg_len = sizeof(*call); ! 436: m = m_get_len(msg_len); ! 437: if (m == NULL) ! 438: return ENOBUFS; ! 439: ! 440: /* ! 441: * Build request message for PMAPPROC_CALLIT. ! 442: */ ! 443: call = mtod(m, struct whoami_call *); ! 444: call->call_prog = htonl(BOOTPARAM_PROG); ! 445: call->call_vers = htonl(BOOTPARAM_VERS); ! 446: call->call_proc = htonl(BOOTPARAM_WHOAMI); ! 447: call->call_arglen = htonl(sizeof(struct bp_inaddr)); ! 448: ! 449: /* client IP address */ ! 450: call->call_ia.atype = htonl(1); ! 451: p = (u_char*)my_ip; ! 452: lp = call->call_ia.addr; ! 453: *lp++ = htonl(*p); p++; ! 454: *lp++ = htonl(*p); p++; ! 455: *lp++ = htonl(*p); p++; ! 456: *lp++ = htonl(*p); p++; ! 457: ! 458: /* RPC: portmap/callit */ ! 459: bpsin->sin_port = htons(PMAPPORT); ! 460: from = NULL; ! 461: error = krpc_call(bpsin, PMAPPROG, PMAPVERS, ! 462: PMAPPROC_CALLIT, &m, &from); ! 463: if (error) ! 464: return error; ! 465: ! 466: /* ! 467: * Parse result message. ! 468: */ ! 469: msg_len = m->m_len; ! 470: lp = mtod(m, long *); ! 471: ! 472: /* bootparam server port (also grab from address). */ ! 473: if (msg_len < sizeof(*lp)) ! 474: goto bad; ! 475: msg_len -= sizeof(*lp); ! 476: bpsin->sin_port = htons((short)ntohl(*lp++)); ! 477: sin = mtod(from, struct sockaddr_in *); ! 478: bpsin->sin_addr.s_addr = sin->sin_addr.s_addr; ! 479: ! 480: /* length of encapsulated results */ ! 481: if (msg_len < (ntohl(*lp) + sizeof(*lp))) ! 482: goto bad; ! 483: msg_len = ntohl(*lp++); ! 484: p = (char*)lp; ! 485: ! 486: /* client name */ ! 487: if (msg_len < sizeof(*str)) ! 488: goto bad; ! 489: str = (struct rpc_string *)p; ! 490: cn_len = ntohl(str->len); ! 491: if (msg_len < cn_len) ! 492: goto bad; ! 493: if (cn_len >= MAXHOSTNAMELEN) ! 494: goto bad; ! 495: bcopy(str->data, hostname, cn_len); ! 496: hostname[cn_len] = '\0'; ! 497: hostnamelen = cn_len; ! 498: p += RPC_STR_SIZE(cn_len); ! 499: msg_len -= RPC_STR_SIZE(cn_len); ! 500: ! 501: /* domain name */ ! 502: if (msg_len < sizeof(*str)) ! 503: goto bad; ! 504: str = (struct rpc_string *)p; ! 505: dn_len = ntohl(str->len); ! 506: if (msg_len < dn_len) ! 507: goto bad; ! 508: if (dn_len >= MAXHOSTNAMELEN) ! 509: goto bad; ! 510: bcopy(str->data, domainname, dn_len); ! 511: domainname[dn_len] = '\0'; ! 512: domainnamelen = dn_len; ! 513: p += RPC_STR_SIZE(dn_len); ! 514: msg_len -= RPC_STR_SIZE(dn_len); ! 515: ! 516: /* gateway address */ ! 517: if (msg_len < sizeof(*bia)) ! 518: goto bad; ! 519: bia = (struct bp_inaddr *)p; ! 520: if (bia->atype != htonl(1)) ! 521: goto bad; ! 522: p = (u_char*)gw_ip; ! 523: *p++ = ntohl(bia->addr[0]); ! 524: *p++ = ntohl(bia->addr[1]); ! 525: *p++ = ntohl(bia->addr[2]); ! 526: *p++ = ntohl(bia->addr[3]); ! 527: goto out; ! 528: ! 529: bad: ! 530: printf("nfs_boot: bootparam_whoami: bad reply\n"); ! 531: error = EBADRPC; ! 532: ! 533: out: ! 534: if (from) ! 535: m_freem(from); ! 536: m_freem(m); ! 537: return(error); ! 538: } ! 539: ! 540: ! 541: /* ! 542: * RPC: bootparam/getfile ! 543: * Given client name and file "key", get: ! 544: * server name ! 545: * server IP address ! 546: * server pathname ! 547: */ ! 548: static int ! 549: bp_getfile(bpsin, key, md_sin, serv_name, pathname) ! 550: struct sockaddr_in *bpsin; ! 551: char *key; ! 552: struct sockaddr_in *md_sin; ! 553: char *serv_name; ! 554: char *pathname; ! 555: { ! 556: struct rpc_string *str; ! 557: struct mbuf *m; ! 558: struct bp_inaddr *bia; ! 559: struct sockaddr_in *sin; ! 560: u_char *p, *q; ! 561: int error, msg_len; ! 562: int cn_len, key_len, sn_len, path_len; ! 563: ! 564: /* ! 565: * Get message buffer of sufficient size. ! 566: */ ! 567: cn_len = hostnamelen; ! 568: key_len = strlen(key); ! 569: msg_len = 0; ! 570: msg_len += RPC_STR_SIZE(cn_len); ! 571: msg_len += RPC_STR_SIZE(key_len); ! 572: m = m_get_len(msg_len); ! 573: if (m == NULL) ! 574: return ENOBUFS; ! 575: ! 576: /* ! 577: * Build request message. ! 578: */ ! 579: p = mtod(m, u_char *); ! 580: bzero(p, msg_len); ! 581: /* client name (hostname) */ ! 582: str = (struct rpc_string *)p; ! 583: str->len = htonl(cn_len); ! 584: bcopy(hostname, str->data, cn_len); ! 585: p += RPC_STR_SIZE(cn_len); ! 586: /* key name (root or swap) */ ! 587: str = (struct rpc_string *)p; ! 588: str->len = htonl(key_len); ! 589: bcopy(key, str->data, key_len); ! 590: ! 591: /* RPC: bootparam/getfile */ ! 592: error = krpc_call(bpsin, BOOTPARAM_PROG, BOOTPARAM_VERS, ! 593: BOOTPARAM_GETFILE, &m, NULL); ! 594: if (error) ! 595: return error; ! 596: ! 597: /* ! 598: * Parse result message. ! 599: */ ! 600: p = mtod(m, u_char *); ! 601: msg_len = m->m_len; ! 602: ! 603: /* server name */ ! 604: if (msg_len < sizeof(*str)) ! 605: goto bad; ! 606: str = (struct rpc_string *)p; ! 607: sn_len = ntohl(str->len); ! 608: if (msg_len < sn_len) ! 609: goto bad; ! 610: if (sn_len >= MNAMELEN) ! 611: goto bad; ! 612: bcopy(str->data, serv_name, sn_len); ! 613: serv_name[sn_len] = '\0'; ! 614: p += RPC_STR_SIZE(sn_len); ! 615: msg_len -= RPC_STR_SIZE(sn_len); ! 616: ! 617: /* server IP address (mountd) */ ! 618: if (msg_len < sizeof(*bia)) ! 619: goto bad; ! 620: bia = (struct bp_inaddr *)p; ! 621: if (bia->atype != htonl(1)) ! 622: goto bad; ! 623: sin = md_sin; ! 624: bzero((caddr_t)sin, sizeof(*sin)); ! 625: sin->sin_len = sizeof(*sin); ! 626: sin->sin_family = AF_INET; ! 627: q = (u_char*) &sin->sin_addr; ! 628: *q++ = ntohl(bia->addr[0]); ! 629: *q++ = ntohl(bia->addr[1]); ! 630: *q++ = ntohl(bia->addr[2]); ! 631: *q++ = ntohl(bia->addr[3]); ! 632: p += sizeof(*bia); ! 633: msg_len -= sizeof(*bia); ! 634: ! 635: /* server pathname */ ! 636: if (msg_len < sizeof(*str)) ! 637: goto bad; ! 638: str = (struct rpc_string *)p; ! 639: path_len = ntohl(str->len); ! 640: if (msg_len < path_len) ! 641: goto bad; ! 642: if (path_len >= MAXPATHLEN) ! 643: goto bad; ! 644: bcopy(str->data, pathname, path_len); ! 645: pathname[path_len] = '\0'; ! 646: goto out; ! 647: ! 648: bad: ! 649: printf("nfs_boot: bootparam_getfile: bad reply\n"); ! 650: error = EBADRPC; ! 651: ! 652: out: ! 653: m_freem(m); ! 654: return(0); ! 655: } ! 656: ! 657: ! 658: /* ! 659: * RPC: mountd/mount ! 660: * Given a server pathname, get an NFS file handle. ! 661: * Also, sets sin->sin_port to the NFS service port. ! 662: */ ! 663: static int ! 664: md_mount(mdsin, path, fhp) ! 665: struct sockaddr_in *mdsin; /* mountd server address */ ! 666: char *path; ! 667: u_char *fhp; ! 668: { ! 669: /* The RPC structures */ ! 670: struct rpc_string *str; ! 671: struct rdata { ! 672: u_long errno; ! 673: u_char fh[NFSX_V2FH]; ! 674: } *rdata; ! 675: struct mbuf *m; ! 676: int error, mlen, slen; ! 677: ! 678: /* Get port number for MOUNTD. */ ! 679: error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, ! 680: &mdsin->sin_port); ! 681: if (error) return error; ! 682: ! 683: slen = strlen(path); ! 684: mlen = RPC_STR_SIZE(slen); ! 685: ! 686: m = m_get_len(mlen); ! 687: if (m == NULL) ! 688: return ENOBUFS; ! 689: str = mtod(m, struct rpc_string *); ! 690: str->len = htonl(slen); ! 691: bcopy(path, str->data, slen); ! 692: ! 693: /* Do RPC to mountd. */ ! 694: error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, ! 695: RPCMNT_MOUNT, &m, NULL); ! 696: if (error) ! 697: return error; /* message already freed */ ! 698: ! 699: mlen = m->m_len; ! 700: if (mlen < sizeof(*rdata)) ! 701: goto bad; ! 702: rdata = mtod(m, struct rdata *); ! 703: error = ntohl(rdata->errno); ! 704: if (error) ! 705: goto bad; ! 706: bcopy(rdata->fh, fhp, NFSX_V2FH); ! 707: ! 708: /* Set port number for NFS use. */ ! 709: error = krpc_portmap(mdsin, NFS_PROG, NFS_VER2, ! 710: &mdsin->sin_port); ! 711: goto out; ! 712: ! 713: bad: ! 714: error = EBADRPC; ! 715: ! 716: out: ! 717: m_freem(m); ! 718: return error; ! 719: } ! 720: ! 721: #endif /* NETHER */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.