1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1999-2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * Subroutines that implement the bootparam services. 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <rpcsvc/bootparam_prot.h> 34*7c478bd9Sstevel@tonic-gate #include <netdb.h> 35*7c478bd9Sstevel@tonic-gate #include <nlist.h> 36*7c478bd9Sstevel@tonic-gate #include <stdio.h> 37*7c478bd9Sstevel@tonic-gate #include <ctype.h> 38*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 39*7c478bd9Sstevel@tonic-gate #include <string.h> 40*7c478bd9Sstevel@tonic-gate #include <nsswitch.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 44*7c478bd9Sstevel@tonic-gate #define KERNEL /* to get RTHASHSIZ */ 45*7c478bd9Sstevel@tonic-gate #include <sys/stream.h> 46*7c478bd9Sstevel@tonic-gate #include <net/route.h> 47*7c478bd9Sstevel@tonic-gate #undef KERNEL 48*7c478bd9Sstevel@tonic-gate #include <net/if.h> /* for structs ifnet and ifaddr */ 49*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 50*7c478bd9Sstevel@tonic-gate #include <netinet/in_var.h> /* for struct in_ifaddr */ 51*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate #include "bootparam_private.h" 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #define LINESIZE 1024 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate extern int getdomainname(char *, int); 58*7c478bd9Sstevel@tonic-gate extern int bootparams_getbyname(char *, char *, int); 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate static char *wildcard = "*"; 61*7c478bd9Sstevel@tonic-gate static char domainkey[] = "domain="; 62*7c478bd9Sstevel@tonic-gate static void getf_printres(bp_getfile_res *); 63*7c478bd9Sstevel@tonic-gate static void copydomain(char *, char *, int); 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate /* 66*7c478bd9Sstevel@tonic-gate * Whoami turns a client address into a client name 67*7c478bd9Sstevel@tonic-gate * and suggested route machine. 68*7c478bd9Sstevel@tonic-gate */ 69*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 70*7c478bd9Sstevel@tonic-gate bp_whoami_res * 71*7c478bd9Sstevel@tonic-gate bootparamproc_whoami_1(bp_whoami_arg *argp, CLIENT *cl) 72*7c478bd9Sstevel@tonic-gate { 73*7c478bd9Sstevel@tonic-gate static bp_whoami_res res; 74*7c478bd9Sstevel@tonic-gate struct in_addr clnt_addr; 75*7c478bd9Sstevel@tonic-gate struct in_addr route_addr; 76*7c478bd9Sstevel@tonic-gate struct hostent *hp; 77*7c478bd9Sstevel@tonic-gate static char clnt_entry[LINESIZE]; 78*7c478bd9Sstevel@tonic-gate static char domain[MAX_MACHINE_NAME]; 79*7c478bd9Sstevel@tonic-gate char *cp; 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate if (argp->client_address.address_type != IP_ADDR_TYPE) { 82*7c478bd9Sstevel@tonic-gate if (debug) { 83*7c478bd9Sstevel@tonic-gate msgout("Whoami failed: unknown address type %d", 84*7c478bd9Sstevel@tonic-gate argp->client_address.address_type); 85*7c478bd9Sstevel@tonic-gate } 86*7c478bd9Sstevel@tonic-gate return (NULL); 87*7c478bd9Sstevel@tonic-gate } 88*7c478bd9Sstevel@tonic-gate (void) memcpy(&clnt_addr, &argp->client_address.bp_address_u.ip_addr, 89*7c478bd9Sstevel@tonic-gate sizeof (clnt_addr)); 90*7c478bd9Sstevel@tonic-gate hp = gethostbyaddr((char *)&clnt_addr, sizeof (clnt_addr), AF_INET); 91*7c478bd9Sstevel@tonic-gate if (hp == NULL) { 92*7c478bd9Sstevel@tonic-gate if (debug) { 93*7c478bd9Sstevel@tonic-gate msgout("Whoami failed: gethostbyaddr for %s.", 94*7c478bd9Sstevel@tonic-gate inet_ntoa(clnt_addr)); 95*7c478bd9Sstevel@tonic-gate } 96*7c478bd9Sstevel@tonic-gate return (NULL); 97*7c478bd9Sstevel@tonic-gate } 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate /* 100*7c478bd9Sstevel@tonic-gate * We only answer requests from clients listed in the database. 101*7c478bd9Sstevel@tonic-gate */ 102*7c478bd9Sstevel@tonic-gate if ((bootparams_getbyname(hp->h_name, clnt_entry, 103*7c478bd9Sstevel@tonic-gate sizeof (clnt_entry)) != __NSW_SUCCESS) && 104*7c478bd9Sstevel@tonic-gate (bootparams_getbyname(wildcard, clnt_entry, 105*7c478bd9Sstevel@tonic-gate sizeof (clnt_entry)) != __NSW_SUCCESS)) 106*7c478bd9Sstevel@tonic-gate return (NULL); 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate res.client_name = hp->h_name; 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate /* 111*7c478bd9Sstevel@tonic-gate * The algorithm for determining the client's domain name is: 112*7c478bd9Sstevel@tonic-gate * 1) look for "domain=" in the client's bootparams line. 113*7c478bd9Sstevel@tonic-gate * If found, use its value. 114*7c478bd9Sstevel@tonic-gate * 2) look for a "domain=" entry in the wildcard bootparams 115*7c478bd9Sstevel@tonic-gate * line (if any). If found, use its value. Otherwise, 116*7c478bd9Sstevel@tonic-gate * 3) return the domain name of the server answering the 117*7c478bd9Sstevel@tonic-gate * request. 118*7c478bd9Sstevel@tonic-gate */ 119*7c478bd9Sstevel@tonic-gate if (cp = strstr(clnt_entry, domainkey)) { 120*7c478bd9Sstevel@tonic-gate copydomain(cp + sizeof (domainkey) - 1, domain, 121*7c478bd9Sstevel@tonic-gate sizeof (domain)); 122*7c478bd9Sstevel@tonic-gate } else { 123*7c478bd9Sstevel@tonic-gate /* "domain=" not found - try for wildcard */ 124*7c478bd9Sstevel@tonic-gate if ((bootparams_getbyname(wildcard, clnt_entry, 125*7c478bd9Sstevel@tonic-gate sizeof (clnt_entry)) == __NSW_SUCCESS) && 126*7c478bd9Sstevel@tonic-gate (cp = strstr(clnt_entry, domainkey))) { 127*7c478bd9Sstevel@tonic-gate copydomain(cp + sizeof (domainkey) - 1, domain, 128*7c478bd9Sstevel@tonic-gate sizeof (domain)); 129*7c478bd9Sstevel@tonic-gate } else { 130*7c478bd9Sstevel@tonic-gate (void) getdomainname(domain, sizeof (domain)); 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate res.domain_name = domain; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate res.router_address.address_type = IP_ADDR_TYPE; 136*7c478bd9Sstevel@tonic-gate route_addr.s_addr = get_ip_route(clnt_addr); 137*7c478bd9Sstevel@tonic-gate (void) memcpy(&res.router_address.bp_address_u.ip_addr, 138*7c478bd9Sstevel@tonic-gate &route_addr, 139*7c478bd9Sstevel@tonic-gate sizeof (res.router_address.bp_address_u.ip_addr)); 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate if (debug) { 142*7c478bd9Sstevel@tonic-gate struct in_addr in; 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate (void) memcpy(&in.s_addr, 145*7c478bd9Sstevel@tonic-gate &res.router_address.bp_address_u.ip_addr, 146*7c478bd9Sstevel@tonic-gate sizeof (in.s_addr)); 147*7c478bd9Sstevel@tonic-gate msgout("Whoami returning name = %s, router address = %s", 148*7c478bd9Sstevel@tonic-gate res.client_name, 149*7c478bd9Sstevel@tonic-gate inet_ntoa(in)); 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate return (&res); 152*7c478bd9Sstevel@tonic-gate } 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate /* 155*7c478bd9Sstevel@tonic-gate * Getfile gets the client name and the key and returns its server 156*7c478bd9Sstevel@tonic-gate * and the pathname for that key. 157*7c478bd9Sstevel@tonic-gate */ 158*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 159*7c478bd9Sstevel@tonic-gate bp_getfile_res * 160*7c478bd9Sstevel@tonic-gate bootparamproc_getfile_1(bp_getfile_arg *argp, CLIENT *cl) 161*7c478bd9Sstevel@tonic-gate { 162*7c478bd9Sstevel@tonic-gate static bp_getfile_res res; 163*7c478bd9Sstevel@tonic-gate static char clnt_entry[LINESIZE]; 164*7c478bd9Sstevel@tonic-gate struct hostent *hp; 165*7c478bd9Sstevel@tonic-gate char *cp; 166*7c478bd9Sstevel@tonic-gate char filekey[LINESIZE]; 167*7c478bd9Sstevel@tonic-gate char *server_hostname; 168*7c478bd9Sstevel@tonic-gate char *path_on_server; 169*7c478bd9Sstevel@tonic-gate int do_wildcard = 0; 170*7c478bd9Sstevel@tonic-gate static char *zero_len_string = ""; 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate /* 173*7c478bd9Sstevel@tonic-gate * The bootparams_getbyname() library function looks up a 174*7c478bd9Sstevel@tonic-gate * "client entry" using using the client's hostname as the 175*7c478bd9Sstevel@tonic-gate * key. A client entry consists of a string of "file entries" 176*7c478bd9Sstevel@tonic-gate * separated by white space. Each file entry is of the form: 177*7c478bd9Sstevel@tonic-gate * 178*7c478bd9Sstevel@tonic-gate * file_key=server_hostname:path_on_server 179*7c478bd9Sstevel@tonic-gate * 180*7c478bd9Sstevel@tonic-gate * In the getfile RPC call, the client gives us his hostname 181*7c478bd9Sstevel@tonic-gate * and a file_key. We lookup his client entry, then locate a 182*7c478bd9Sstevel@tonic-gate * file entry matching that file_key. We then parse out the 183*7c478bd9Sstevel@tonic-gate * server_hostname and path_on_server from the file entry, map 184*7c478bd9Sstevel@tonic-gate * the server_hostname to an IP address, and return both the 185*7c478bd9Sstevel@tonic-gate * IP address and path_on_server back to the client. 186*7c478bd9Sstevel@tonic-gate */ 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate /* make the client's file key int a string we can use for matching */ 189*7c478bd9Sstevel@tonic-gate (void) strncpy(filekey, argp->file_id, sizeof (filekey) - 2); 190*7c478bd9Sstevel@tonic-gate filekey[sizeof (filekey) - 2] = '\0'; 191*7c478bd9Sstevel@tonic-gate (void) strcat(filekey, "="); 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate if (bootparams_getbyname(argp->client_name, clnt_entry, 194*7c478bd9Sstevel@tonic-gate sizeof (clnt_entry)) == __NSW_SUCCESS) { 195*7c478bd9Sstevel@tonic-gate /* locate the file_key in the client's entry */ 196*7c478bd9Sstevel@tonic-gate cp = strstr(clnt_entry, filekey); 197*7c478bd9Sstevel@tonic-gate if (cp == NULL) 198*7c478bd9Sstevel@tonic-gate do_wildcard++; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate } else 201*7c478bd9Sstevel@tonic-gate do_wildcard++; 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate if (do_wildcard) { 204*7c478bd9Sstevel@tonic-gate if (bootparams_getbyname(wildcard, clnt_entry, 205*7c478bd9Sstevel@tonic-gate sizeof (clnt_entry)) != __NSW_SUCCESS) 206*7c478bd9Sstevel@tonic-gate return (NULL); 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate /* locate the file_key in the client's entry */ 209*7c478bd9Sstevel@tonic-gate cp = strstr(clnt_entry, filekey); 210*7c478bd9Sstevel@tonic-gate if (cp == NULL) 211*7c478bd9Sstevel@tonic-gate return (NULL); 212*7c478bd9Sstevel@tonic-gate } 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate /* locate the "data" part of file entry (r.h.s. of "=") */ 215*7c478bd9Sstevel@tonic-gate cp = strchr(cp, '='); 216*7c478bd9Sstevel@tonic-gate if (cp == NULL) 217*7c478bd9Sstevel@tonic-gate return (NULL); 218*7c478bd9Sstevel@tonic-gate cp++; 219*7c478bd9Sstevel@tonic-gate if (*cp == '\0') 220*7c478bd9Sstevel@tonic-gate return (NULL); 221*7c478bd9Sstevel@tonic-gate server_hostname = cp; 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate /* null-terminate server_hostname and parse path_on_server */ 224*7c478bd9Sstevel@tonic-gate cp = strchr(server_hostname, ':'); 225*7c478bd9Sstevel@tonic-gate if (cp == NULL) 226*7c478bd9Sstevel@tonic-gate return (NULL); 227*7c478bd9Sstevel@tonic-gate *cp = '\0'; 228*7c478bd9Sstevel@tonic-gate cp++; 229*7c478bd9Sstevel@tonic-gate /* strtok() will null-terminate path_on_server */ 230*7c478bd9Sstevel@tonic-gate path_on_server = strtok(cp, "\t\n "); 231*7c478bd9Sstevel@tonic-gate if (path_on_server == NULL) 232*7c478bd9Sstevel@tonic-gate path_on_server = zero_len_string; 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate res.server_name = server_hostname; 235*7c478bd9Sstevel@tonic-gate res.server_path = path_on_server; 236*7c478bd9Sstevel@tonic-gate if (*res.server_name == 0) { 237*7c478bd9Sstevel@tonic-gate res.server_address.address_type = IP_ADDR_TYPE; 238*7c478bd9Sstevel@tonic-gate (void) memset(&res.server_address.bp_address_u.ip_addr, 0, 239*7c478bd9Sstevel@tonic-gate sizeof (res.server_address.bp_address_u.ip_addr)); 240*7c478bd9Sstevel@tonic-gate } else { 241*7c478bd9Sstevel@tonic-gate in_addr_t addr; 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate if ((hp = gethostbyname(server_hostname)) != NULL) { 244*7c478bd9Sstevel@tonic-gate addr = find_best_server_int(hp->h_addr_list, 245*7c478bd9Sstevel@tonic-gate argp->client_name); 246*7c478bd9Sstevel@tonic-gate } else { 247*7c478bd9Sstevel@tonic-gate addr = inet_addr(server_hostname); 248*7c478bd9Sstevel@tonic-gate if (addr == INADDR_BROADCAST) { 249*7c478bd9Sstevel@tonic-gate if (debug) { 250*7c478bd9Sstevel@tonic-gate msgout("getfile_1: gethostbyname(%s) " 251*7c478bd9Sstevel@tonic-gate "failed", res.server_name); 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate return (NULL); 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate res.server_address.address_type = IP_ADDR_TYPE; 257*7c478bd9Sstevel@tonic-gate (void) memcpy(&res.server_address.bp_address_u.ip_addr, 258*7c478bd9Sstevel@tonic-gate &addr, sizeof (res.server_address.bp_address_u.ip_addr)); 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate if (debug) { 261*7c478bd9Sstevel@tonic-gate getf_printres(&res); 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate return (&res); 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate void 267*7c478bd9Sstevel@tonic-gate getf_printres(bp_getfile_res *res) 268*7c478bd9Sstevel@tonic-gate { 269*7c478bd9Sstevel@tonic-gate struct in_addr in; 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate (void) memcpy(&in.s_addr, &res->server_address.bp_address_u.ip_addr, 272*7c478bd9Sstevel@tonic-gate sizeof (in.s_addr)); 273*7c478bd9Sstevel@tonic-gate msgout("getfile_1: file is \"%s\" %s \"%s\"", 274*7c478bd9Sstevel@tonic-gate res->server_name, 275*7c478bd9Sstevel@tonic-gate inet_ntoa(in), 276*7c478bd9Sstevel@tonic-gate res->server_path); 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate /* 280*7c478bd9Sstevel@tonic-gate * Used when we've found a "domain=" key, this function copies characters 281*7c478bd9Sstevel@tonic-gate * from source to target until we come upon either a NULL or whitespace is 282*7c478bd9Sstevel@tonic-gate * found in the source string, or we run out of room in the target. 283*7c478bd9Sstevel@tonic-gate * 284*7c478bd9Sstevel@tonic-gate */ 285*7c478bd9Sstevel@tonic-gate void 286*7c478bd9Sstevel@tonic-gate copydomain(char *source, char *target, int len) 287*7c478bd9Sstevel@tonic-gate { 288*7c478bd9Sstevel@tonic-gate int n; /* number of characters copies */; 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate len--; /* leave room for terminating '\0' */ 291*7c478bd9Sstevel@tonic-gate if (source) 292*7c478bd9Sstevel@tonic-gate for (n = 0; *source != '\0' && n < len; n++) 293*7c478bd9Sstevel@tonic-gate if (isspace((int)*source)) 294*7c478bd9Sstevel@tonic-gate break; 295*7c478bd9Sstevel@tonic-gate else 296*7c478bd9Sstevel@tonic-gate *target++ = *source++; 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate *target = '\0'; 299*7c478bd9Sstevel@tonic-gate } 300