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