Annotation of sys/lib/libsa/bootparam.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: bootparam.c,v 1.11 2003/08/11 06:23:09 deraadt Exp $ */
! 2: /* $NetBSD: bootparam.c,v 1.10 1996/10/14 21:16:55 thorpej Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995 Gordon W. Ross
! 6: * All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. The name of the author may not be used to endorse or promote products
! 17: * derived from this software without specific prior written permission.
! 18: * 4. All advertising materials mentioning features or use of this software
! 19: * must display the following acknowledgement:
! 20: * This product includes software developed by Gordon W. Ross
! 21: *
! 22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 32: */
! 33:
! 34: /*
! 35: * RPC/bootparams
! 36: */
! 37:
! 38: #include <sys/param.h>
! 39: #include <sys/socket.h>
! 40:
! 41: #include <net/if.h>
! 42:
! 43: #include <netinet/in.h>
! 44: #include <netinet/in_systm.h>
! 45:
! 46: #include <nfs/rpcv2.h>
! 47:
! 48: #include "stand.h"
! 49: #include "net.h"
! 50: #include "netif.h"
! 51: #include "rpc.h"
! 52: #include "bootparam.h"
! 53:
! 54: #ifdef DEBUG_RPC
! 55: #define RPC_PRINTF(a) printf a
! 56: #else
! 57: #define RPC_PRINTF(a) /* printf a */
! 58: #endif
! 59:
! 60: struct in_addr bp_server_addr; /* net order */
! 61: n_short bp_server_port; /* net order */
! 62:
! 63: /*
! 64: * RPC definitions for bootparamd
! 65: */
! 66: #define BOOTPARAM_PROG 100026
! 67: #define BOOTPARAM_VERS 1
! 68: #define BOOTPARAM_WHOAMI 1
! 69: #define BOOTPARAM_GETFILE 2
! 70:
! 71: /*
! 72: * Inet address in RPC messages
! 73: * (Note, really four ints, NOT chars. Blech.)
! 74: */
! 75: struct xdr_inaddr {
! 76: u_int32_t atype;
! 77: int32_t addr[4];
! 78: };
! 79:
! 80: int xdr_inaddr_encode(char **p, struct in_addr ia);
! 81: int xdr_inaddr_decode(char **p, struct in_addr *ia);
! 82:
! 83: int xdr_string_encode(char **p, char *str, int len);
! 84: int xdr_string_decode(char **p, char *str, int *len_p);
! 85:
! 86:
! 87: /*
! 88: * RPC: bootparam/whoami
! 89: * Given client IP address, get:
! 90: * client name (hostname)
! 91: * domain name (domainname)
! 92: * gateway address
! 93: *
! 94: * The hostname and domainname are set here for convenience.
! 95: *
! 96: * Note - bpsin is initialized to the broadcast address,
! 97: * and will be replaced with the bootparam server address
! 98: * after this call is complete. Have to use PMAP_PROC_CALL
! 99: * to make sure we get responses only from a servers that
! 100: * know about us (don't want to broadcast a getport call).
! 101: */
! 102: int
! 103: bp_whoami(int sockfd)
! 104: {
! 105: /* RPC structures for PMAPPROC_CALLIT */
! 106: struct args {
! 107: u_int32_t prog;
! 108: u_int32_t vers;
! 109: u_int32_t proc;
! 110: u_int32_t arglen;
! 111: struct xdr_inaddr xina;
! 112: } *args;
! 113: struct repl {
! 114: u_int16_t _pad;
! 115: u_int16_t port;
! 116: u_int32_t encap_len;
! 117: /* encapsulated data here */
! 118: n_long capsule[64];
! 119: } *repl;
! 120: struct {
! 121: n_long h[RPC_HEADER_WORDS];
! 122: struct args d;
! 123: } sdata;
! 124: struct {
! 125: n_long h[RPC_HEADER_WORDS];
! 126: struct repl d;
! 127: } rdata;
! 128: char *send_tail, *recv_head;
! 129: struct iodesc *d;
! 130: int len, x;
! 131:
! 132: RPC_PRINTF(("bp_whoami: myip=%s\n", inet_ntoa(myip)));
! 133:
! 134: if (!(d = socktodesc(sockfd))) {
! 135: RPC_PRINTF(("bp_whoami: bad socket. %d\n", sockfd));
! 136: return (-1);
! 137: }
! 138: args = &sdata.d;
! 139: repl = &rdata.d;
! 140:
! 141: /*
! 142: * Build request args for PMAPPROC_CALLIT.
! 143: */
! 144: args->prog = htonl(BOOTPARAM_PROG);
! 145: args->vers = htonl(BOOTPARAM_VERS);
! 146: args->proc = htonl(BOOTPARAM_WHOAMI);
! 147: args->arglen = htonl(sizeof(struct xdr_inaddr));
! 148: send_tail = (char *)&args->xina;
! 149:
! 150: /*
! 151: * append encapsulated data (client IP address)
! 152: */
! 153: if (xdr_inaddr_encode(&send_tail, myip))
! 154: return (-1);
! 155:
! 156: /* RPC: portmap/callit */
! 157: d->myport = htons(--rpc_port);
! 158: d->destip.s_addr = INADDR_BROADCAST; /* XXX: subnet bcast? */
! 159: /* rpc_call will set d->destport */
! 160:
! 161: len = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_CALLIT,
! 162: args, send_tail - (char *)args,
! 163: repl, sizeof(*repl));
! 164: if (len < 8) {
! 165: printf("bootparamd: 'whoami' call failed\n");
! 166: return (-1);
! 167: }
! 168:
! 169: /* Save bootparam server address (from IP header). */
! 170: rpc_fromaddr(repl, &bp_server_addr, &bp_server_port);
! 171:
! 172: /*
! 173: * Note that bp_server_port is now 111 due to the
! 174: * indirect call (using PMAPPROC_CALLIT), so get the
! 175: * actual port number from the reply data.
! 176: */
! 177: bp_server_port = repl->port;
! 178:
! 179: RPC_PRINTF(("bp_whoami: server at %s:%d\n",
! 180: inet_ntoa(bp_server_addr), ntohs(bp_server_port)));
! 181:
! 182: /* We have just done a portmap call, so cache the portnum. */
! 183: rpc_pmap_putcache(bp_server_addr, BOOTPARAM_PROG, BOOTPARAM_VERS,
! 184: (int)ntohs(bp_server_port));
! 185:
! 186: /*
! 187: * Parse the encapsulated results from bootparam/whoami
! 188: */
! 189: x = ntohl(repl->encap_len);
! 190: if (len < x) {
! 191: printf("bp_whoami: short reply, %d < %d\n", len, x);
! 192: return (-1);
! 193: }
! 194: recv_head = (char *)repl->capsule;
! 195:
! 196: /* client name */
! 197: hostnamelen = MAXHOSTNAMELEN-1;
! 198: if (xdr_string_decode(&recv_head, hostname, &hostnamelen)) {
! 199: RPC_PRINTF(("bp_whoami: bad hostname\n"));
! 200: return (-1);
! 201: }
! 202:
! 203: /* domain name */
! 204: domainnamelen = MAXHOSTNAMELEN-1;
! 205: if (xdr_string_decode(&recv_head, domainname, &domainnamelen)) {
! 206: RPC_PRINTF(("bp_whoami: bad domainname\n"));
! 207: return (-1);
! 208: }
! 209:
! 210: /* gateway address */
! 211: if (xdr_inaddr_decode(&recv_head, &gateip)) {
! 212: RPC_PRINTF(("bp_whoami: bad gateway\n"));
! 213: return (-1);
! 214: }
! 215:
! 216: /* success */
! 217: return(0);
! 218: }
! 219:
! 220:
! 221: /*
! 222: * RPC: bootparam/getfile
! 223: * Given client name and file "key", get:
! 224: * server name
! 225: * server IP address
! 226: * server pathname
! 227: */
! 228: int
! 229: bp_getfile(int sockfd, char *key, struct in_addr *serv_addr, char *pathname)
! 230: {
! 231: struct {
! 232: n_long h[RPC_HEADER_WORDS];
! 233: n_long d[64];
! 234: } sdata;
! 235: struct {
! 236: n_long h[RPC_HEADER_WORDS];
! 237: n_long d[128];
! 238: } rdata;
! 239: char serv_name[FNAME_SIZE];
! 240: char *send_tail, *recv_head;
! 241: /* misc... */
! 242: struct iodesc *d;
! 243: int sn_len, path_len, rlen;
! 244:
! 245: if (!(d = socktodesc(sockfd))) {
! 246: RPC_PRINTF(("bp_getfile: bad socket. %d\n", sockfd));
! 247: return (-1);
! 248: }
! 249:
! 250: send_tail = (char *)sdata.d;
! 251: recv_head = (char *)rdata.d;
! 252:
! 253: /*
! 254: * Build request message.
! 255: */
! 256:
! 257: /* client name (hostname) */
! 258: if (xdr_string_encode(&send_tail, hostname, hostnamelen)) {
! 259: RPC_PRINTF(("bp_getfile: bad client\n"));
! 260: return (-1);
! 261: }
! 262:
! 263: /* key name (root or swap) */
! 264: if (xdr_string_encode(&send_tail, key, strlen(key))) {
! 265: RPC_PRINTF(("bp_getfile: bad key\n"));
! 266: return (-1);
! 267: }
! 268:
! 269: /* RPC: bootparam/getfile */
! 270: d->myport = htons(--rpc_port);
! 271: d->destip = bp_server_addr;
! 272: /* rpc_call will set d->destport */
! 273:
! 274: rlen = rpc_call(d,
! 275: BOOTPARAM_PROG, BOOTPARAM_VERS, BOOTPARAM_GETFILE,
! 276: sdata.d, send_tail - (char *)sdata.d,
! 277: rdata.d, sizeof(rdata.d));
! 278: if (rlen < 4) {
! 279: RPC_PRINTF(("bp_getfile: short reply\n"));
! 280: errno = EBADRPC;
! 281: return (-1);
! 282: }
! 283: recv_head = (char *)rdata.d;
! 284:
! 285: /*
! 286: * Parse result message.
! 287: */
! 288:
! 289: /* server name */
! 290: sn_len = FNAME_SIZE-1;
! 291: if (xdr_string_decode(&recv_head, serv_name, &sn_len)) {
! 292: RPC_PRINTF(("bp_getfile: bad server name\n"));
! 293: return (-1);
! 294: }
! 295:
! 296: /* server IP address (mountd/NFS) */
! 297: if (xdr_inaddr_decode(&recv_head, serv_addr)) {
! 298: RPC_PRINTF(("bp_getfile: bad server addr\n"));
! 299: return (-1);
! 300: }
! 301:
! 302: /* server pathname */
! 303: path_len = MAXPATHLEN-1;
! 304: if (xdr_string_decode(&recv_head, pathname, &path_len)) {
! 305: RPC_PRINTF(("bp_getfile: bad server path\n"));
! 306: return (-1);
! 307: }
! 308:
! 309: /* success */
! 310: return(0);
! 311: }
! 312:
! 313:
! 314: /*
! 315: * eXternal Data Representation routines.
! 316: * (but with non-standard args...)
! 317: */
! 318:
! 319: int
! 320: xdr_string_encode(char **pkt, char *str, int len)
! 321: {
! 322: u_int32_t *lenp;
! 323: char *datap;
! 324: int padlen = (len + 3) & ~3; /* padded length */
! 325:
! 326: /* The data will be int aligned. */
! 327: lenp = (u_int32_t*) *pkt;
! 328: *pkt += sizeof(*lenp);
! 329: *lenp = htonl(len);
! 330:
! 331: datap = *pkt;
! 332: *pkt += padlen;
! 333: bcopy(str, datap, len);
! 334:
! 335: return (0);
! 336: }
! 337:
! 338: int
! 339: xdr_string_decode(char **pkt, char *str, int *len_p)
! 340: {
! 341: u_int32_t *lenp;
! 342: char *datap;
! 343: int slen; /* string length */
! 344: int plen; /* padded length */
! 345:
! 346: /* The data will be int aligned. */
! 347: lenp = (u_int32_t*) *pkt;
! 348: *pkt += sizeof(*lenp);
! 349: slen = ntohl(*lenp);
! 350: plen = (slen + 3) & ~3;
! 351:
! 352: if (slen > *len_p)
! 353: slen = *len_p;
! 354: datap = *pkt;
! 355: *pkt += plen;
! 356: bcopy(datap, str, slen);
! 357:
! 358: str[slen] = '\0';
! 359: *len_p = slen;
! 360:
! 361: return (0);
! 362: }
! 363:
! 364: int
! 365: xdr_inaddr_encode(char **pkt, struct in_addr ia)
! 366: {
! 367: struct xdr_inaddr *xi;
! 368: u_char *cp;
! 369: int32_t *ip;
! 370: union {
! 371: n_long l; /* network order */
! 372: u_char c[4];
! 373: } uia;
! 374:
! 375: /* The data will be int aligned. */
! 376: xi = (struct xdr_inaddr *) *pkt;
! 377: *pkt += sizeof(*xi);
! 378: xi->atype = htonl(1);
! 379: uia.l = ia.s_addr;
! 380: cp = uia.c;
! 381: ip = xi->addr;
! 382: /*
! 383: * Note: the htonl() calls below DO NOT
! 384: * imply that uia.l is in host order.
! 385: * In fact this needs it in net order.
! 386: */
! 387: *ip++ = htonl((unsigned int)*cp++);
! 388: *ip++ = htonl((unsigned int)*cp++);
! 389: *ip++ = htonl((unsigned int)*cp++);
! 390: *ip++ = htonl((unsigned int)*cp++);
! 391:
! 392: return (0);
! 393: }
! 394:
! 395: int
! 396: xdr_inaddr_decode(char **pkt, struct in_addr *ia)
! 397: {
! 398: struct xdr_inaddr *xi;
! 399: u_char *cp;
! 400: int32_t *ip;
! 401: union {
! 402: n_long l; /* network order */
! 403: u_char c[4];
! 404: } uia;
! 405:
! 406: /* The data will be int aligned. */
! 407: xi = (struct xdr_inaddr *) *pkt;
! 408: *pkt += sizeof(*xi);
! 409: if (xi->atype != htonl(1)) {
! 410: RPC_PRINTF(("xdr_inaddr_decode: bad addrtype=%d\n",
! 411: ntohl(xi->atype)));
! 412: return(-1);
! 413: }
! 414:
! 415: cp = uia.c;
! 416: ip = xi->addr;
! 417: /*
! 418: * Note: the ntohl() calls below DO NOT
! 419: * imply that uia.l is in host order.
! 420: * In fact this needs it in net order.
! 421: */
! 422: *cp++ = ntohl(*ip++);
! 423: *cp++ = ntohl(*ip++);
! 424: *cp++ = ntohl(*ip++);
! 425: *cp++ = ntohl(*ip++);
! 426: ia->s_addr = uia.l;
! 427:
! 428: return (0);
! 429: }
CVSweb