/* * Request a port number from the port mapper. * Returns the port in host order. */ int rpc_getport(struct iodesc *d, n_long prog, n_long vers) { struct args { n_long prog; /* call program */ n_long vers; /* call version */ n_long proto; /* call protocol */ n_long port; /* call port (unused) */ } *args; struct res { n_long port; } *res; struct { n_long h[RPC_HEADER_WORDS]; struct args d; } sdata; struct { n_long h[RPC_HEADER_WORDS]; struct res d; n_long pad; } rdata; ssize_t cc; int port; #ifdef RPC_DEBUG if (debug) printf("getport: prog=0x%x vers=%d\n", prog, vers); #endif /* This one is fixed forever. */ if (prog == PMAPPROG) return (PMAPPORT); /* Try for cached answer first */ port = rpc_pmap_getcache(d->destip, prog, vers); if (port != -1) return (port); args = &sdata.d; args->prog = htonl(prog); args->vers = htonl(vers); args->proto = htonl(IPPROTO_UDP); args->port = 0; res = &rdata.d; cc = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT, args, sizeof(*args), res, sizeof(*res)); if (cc < 0 || (size_t)cc < sizeof(*res)) { printf("getport: %s", strerror(errno)); errno = EBADRPC; return (-1); } port = (int)ntohl(res->port); rpc_pmap_putcache(d->destip, prog, vers, port); return (port); }
/* * RPC: bootparam/whoami * Given client IP address, get: * client name (hostname) * domain name (domainname) * gateway address * * The hostname and domainname are set here for convenience. * * Note - bpsin is initialized to the broadcast address, * and will be replaced with the bootparam server address * after this call is complete. Have to use PMAP_PROC_CALL * to make sure we get responses only from a servers that * know about us (don't want to broadcast a getport call). */ int bp_whoami(int sockfd) { /* RPC structures for PMAPPROC_CALLIT */ struct args { u_int32_t prog; u_int32_t vers; u_int32_t proc; u_int32_t arglen; struct xdr_inaddr xina; } *args; struct repl { u_int16_t _pad; u_int16_t port; u_int32_t encap_len; /* encapsulated data here */ n_long capsule[64]; } *repl; struct { n_long h[RPC_HEADER_WORDS]; struct args d; } sdata; struct { n_long h[RPC_HEADER_WORDS]; struct repl d; } rdata; char *send_tail, *recv_head; struct iodesc *d; int len, x; RPC_PRINTF(("bp_whoami: myip=%s\n", inet_ntoa(myip))); if (!(d = socktodesc(sockfd))) { RPC_PRINTF(("bp_whoami: bad socket. %d\n", sockfd)); return (-1); } args = &sdata.d; repl = &rdata.d; /* * Build request args for PMAPPROC_CALLIT. */ args->prog = htonl(BOOTPARAM_PROG); args->vers = htonl(BOOTPARAM_VERS); args->proc = htonl(BOOTPARAM_WHOAMI); args->arglen = htonl(sizeof(struct xdr_inaddr)); send_tail = (char *)&args->xina; /* * append encapsulated data (client IP address) */ if (xdr_inaddr_encode(&send_tail, myip)) return (-1); /* RPC: portmap/callit */ d->myport = htons(--rpc_port); d->destip.s_addr = INADDR_BROADCAST; /* XXX: subnet bcast? */ /* rpc_call will set d->destport */ len = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_CALLIT, args, send_tail - (char *)args, repl, sizeof(*repl)); if (len < 8) { printf("bootparamd: 'whoami' call failed\n"); return (-1); } /* Save bootparam server address (from IP header). */ rpc_fromaddr(repl, &bp_server_addr, &bp_server_port); /* * Note that bp_server_port is now 111 due to the * indirect call (using PMAPPROC_CALLIT), so get the * actual port number from the reply data. */ bp_server_port = repl->port; RPC_PRINTF(("bp_whoami: server at %s:%d\n", inet_ntoa(bp_server_addr), ntohs(bp_server_port))); /* We have just done a portmap call, so cache the portnum. */ rpc_pmap_putcache(bp_server_addr, BOOTPARAM_PROG, BOOTPARAM_VERS, (int)ntohs(bp_server_port)); /* * Parse the encapsulated results from bootparam/whoami */ x = ntohl(repl->encap_len); if (len < x) { printf("bp_whoami: short reply, %d < %d\n", len, x); return (-1); } recv_head = (char *)repl->capsule; /* client name */ hostnamelen = MAXHOSTNAMELEN-1; if (xdr_string_decode(&recv_head, hostname, &hostnamelen)) { RPC_PRINTF(("bp_whoami: bad hostname\n")); return (-1); } /* domain name */ domainnamelen = MAXHOSTNAMELEN-1; if (xdr_string_decode(&recv_head, domainname, &domainnamelen)) { RPC_PRINTF(("bp_whoami: bad domainname\n")); return (-1); } /* gateway address */ if (xdr_inaddr_decode(&recv_head, &gateip)) { RPC_PRINTF(("bp_whoami: bad gateway\n")); return (-1); } /* success */ return(0); }