4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 1999-2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2016 by Delphix. All rights reserved.
28 #pragma ident "%Z%%M% %I% %E% SMI"
31 * Subroutines that implement the bootparam services.
34 #include <rpcsvc/bootparam_prot.h>
42 #include <sys/types.h>
44 #include <sys/socket.h>
45 #define KERNEL /* to get RTHASHSIZ */
46 #include <sys/stream.h>
47 #include <net/route.h>
49 #include <net/if.h> /* for structs ifnet and ifaddr */
50 #include <netinet/in.h>
51 #include <netinet/in_var.h> /* for struct in_ifaddr */
52 #include <arpa/inet.h>
54 #include "bootparam_private.h"
58 extern int getdomainname(char *, int);
59 extern int bootparams_getbyname(char *, char *, int);
61 static char *wildcard
= "*";
62 static char domainkey
[] = "domain=";
63 static void getf_printres(bp_getfile_res
*);
64 static void copydomain(char *, char *, int);
67 * Whoami turns a client address into a client name
68 * and suggested route machine.
72 bootparamproc_whoami_1(bp_whoami_arg
*argp
, CLIENT
*cl
)
74 static bp_whoami_res res
;
75 struct in_addr clnt_addr
;
76 struct in_addr route_addr
;
78 static char clnt_entry
[LINESIZE
];
79 static char domain
[MAX_MACHINE_NAME
];
82 if (argp
->client_address
.address_type
!= IP_ADDR_TYPE
) {
84 msgout("Whoami failed: unknown address type %d",
85 argp
->client_address
.address_type
);
89 (void) memcpy(&clnt_addr
, &argp
->client_address
.bp_address_u
.ip_addr
,
91 hp
= gethostbyaddr((char *)&clnt_addr
, sizeof (clnt_addr
), AF_INET
);
94 msgout("Whoami failed: gethostbyaddr for %s.",
95 inet_ntoa(clnt_addr
));
101 * We only answer requests from clients listed in the database.
103 if ((bootparams_getbyname(hp
->h_name
, clnt_entry
,
104 sizeof (clnt_entry
)) != __NSW_SUCCESS
) &&
105 (bootparams_getbyname(wildcard
, clnt_entry
,
106 sizeof (clnt_entry
)) != __NSW_SUCCESS
))
109 res
.client_name
= hp
->h_name
;
112 * The algorithm for determining the client's domain name is:
113 * 1) look for "domain=" in the client's bootparams line.
114 * If found, use its value.
115 * 2) look for a "domain=" entry in the wildcard bootparams
116 * line (if any). If found, use its value. Otherwise,
117 * 3) return the domain name of the server answering the
120 if (cp
= strstr(clnt_entry
, domainkey
)) {
121 copydomain(cp
+ sizeof (domainkey
) - 1, domain
,
124 /* "domain=" not found - try for wildcard */
125 if ((bootparams_getbyname(wildcard
, clnt_entry
,
126 sizeof (clnt_entry
)) == __NSW_SUCCESS
) &&
127 (cp
= strstr(clnt_entry
, domainkey
))) {
128 copydomain(cp
+ sizeof (domainkey
) - 1, domain
,
131 (void) getdomainname(domain
, sizeof (domain
));
134 res
.domain_name
= domain
;
136 res
.router_address
.address_type
= IP_ADDR_TYPE
;
137 route_addr
.s_addr
= get_ip_route(clnt_addr
);
138 (void) memcpy(&res
.router_address
.bp_address_u
.ip_addr
,
140 sizeof (res
.router_address
.bp_address_u
.ip_addr
));
145 (void) memcpy(&in
.s_addr
,
146 &res
.router_address
.bp_address_u
.ip_addr
,
148 msgout("Whoami returning name = %s, router address = %s",
156 * Getfile gets the client name and the key and returns its server
157 * and the pathname for that key.
161 bootparamproc_getfile_1(bp_getfile_arg
*argp
, CLIENT
*cl
)
163 static bp_getfile_res res
;
164 static char clnt_entry
[LINESIZE
];
167 char filekey
[LINESIZE
];
168 char *server_hostname
;
169 char *path_on_server
;
171 static char *zero_len_string
= "";
174 * The bootparams_getbyname() library function looks up a
175 * "client entry" using using the client's hostname as the
176 * key. A client entry consists of a string of "file entries"
177 * separated by white space. Each file entry is of the form:
179 * file_key=server_hostname:path_on_server
181 * In the getfile RPC call, the client gives us its hostname
182 * and a file_key. We lookup its client entry, then locate a
183 * file entry matching that file_key. We then parse out the
184 * server_hostname and path_on_server from the file entry, map
185 * the server_hostname to an IP address, and return both the
186 * IP address and path_on_server back to the client.
189 /* make the client's file key int a string we can use for matching */
190 (void) strncpy(filekey
, argp
->file_id
, sizeof (filekey
) - 2);
191 filekey
[sizeof (filekey
) - 2] = '\0';
192 (void) strcat(filekey
, "=");
194 if (bootparams_getbyname(argp
->client_name
, clnt_entry
,
195 sizeof (clnt_entry
)) == __NSW_SUCCESS
) {
196 /* locate the file_key in the client's entry */
197 cp
= strstr(clnt_entry
, filekey
);
205 if (bootparams_getbyname(wildcard
, clnt_entry
,
206 sizeof (clnt_entry
)) != __NSW_SUCCESS
)
209 /* locate the file_key in the client's entry */
210 cp
= strstr(clnt_entry
, filekey
);
215 /* locate the "data" part of file entry (r.h.s. of "=") */
216 cp
= strchr(cp
, '=');
222 server_hostname
= cp
;
224 /* null-terminate server_hostname and parse path_on_server */
225 cp
= strchr(server_hostname
, ':');
230 /* strtok() will null-terminate path_on_server */
231 path_on_server
= strtok(cp
, "\t\n ");
232 if (path_on_server
== NULL
)
233 path_on_server
= zero_len_string
;
235 res
.server_name
= server_hostname
;
236 res
.server_path
= path_on_server
;
237 if (*res
.server_name
== 0) {
238 res
.server_address
.address_type
= IP_ADDR_TYPE
;
239 (void) memset(&res
.server_address
.bp_address_u
.ip_addr
, 0,
240 sizeof (res
.server_address
.bp_address_u
.ip_addr
));
244 if ((hp
= gethostbyname(server_hostname
)) != NULL
) {
245 addr
= find_best_server_int(hp
->h_addr_list
,
248 addr
= inet_addr(server_hostname
);
249 if (addr
== INADDR_BROADCAST
) {
251 msgout("getfile_1: gethostbyname(%s) "
252 "failed", res
.server_name
);
257 res
.server_address
.address_type
= IP_ADDR_TYPE
;
258 (void) memcpy(&res
.server_address
.bp_address_u
.ip_addr
,
259 &addr
, sizeof (res
.server_address
.bp_address_u
.ip_addr
));
268 getf_printres(bp_getfile_res
*res
)
272 (void) memcpy(&in
.s_addr
, &res
->server_address
.bp_address_u
.ip_addr
,
274 msgout("getfile_1: file is \"%s\" %s \"%s\"",
281 * Used when we've found a "domain=" key, this function copies characters
282 * from source to target until we come upon either a NULL or whitespace is
283 * found in the source string, or we run out of room in the target.
287 copydomain(char *source
, char *target
, int len
)
289 int n
; /* number of characters copies */;
291 len
--; /* leave room for terminating '\0' */
293 for (n
= 0; *source
!= '\0' && n
< len
; n
++)
294 if (isspace((int)*source
))
297 *target
++ = *source
++;