2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * This module (residing in lib/afs/librmtsys.a) implements the client side of
12 * the rpc version (via rx) of non-standard system calls. Currently only rpc
13 * calls of setpag, and pioctl are supported.
15 #include <afsconfig.h>
16 #include <afs/param.h>
21 #include <sys/types.h>
27 #include <netinet/in.h>
42 #include "sys_prototypes.h"
45 #define NOPAG 0xffffffff /* Also defined in afs/afs.h */
46 static afs_int32 hostAddr = 0;
47 static int hostAddrLookup = 0;
48 char *afs_server = 0, server_name[128];
49 static afs_int32 SetClientCreds(struct clientcred *creds, afs_uint32 * groups);
50 int afs_get_pag_from_groups(afs_uint32 g0, afs_uint32 g1);
51 void afs_get_groups_from_pag(afs_uint32 pag, afs_uint32 * g0p, afs_uint32 * g1p);
53 /* Picks up the name of the remote afs client host where the rmtsys
54 * daemon resides. Since the clients may be diskless and/or readonly
55 * ones we felt it's better to rely on an shell environment
56 * (AFSSERVER) for the host name first. If that is not set, the
57 * $HOME/.AFSSERVER file is checked, otherwise the "/.AFSSERVER" is
61 GetAfsServerAddr(char *syscall)
63 register struct hostent *th;
66 /* Take advantage of caching and assume that the remote host
67 * address won't change during a single program's invocation.
73 if (!(afs_server = getenv("AFSSERVER"))) {
78 if (!(home_dir = getenv("HOME"))) {
79 /* Our last chance is the "/.AFSSERVER" file */
80 fp = fopen("/.AFSSERVER", "r");
84 fgets(server_name, 128, fp);
89 sprintf(pathname, "%s/%s", home_dir, ".AFSSERVER");
90 fp = fopen(pathname, "r");
92 /* Our last chance is the "/.AFSSERVER" file */
93 fp = fopen("/.AFSSERVER", "r");
98 fgets(server_name, 128, fp);
101 len = strlen(server_name);
105 if (server_name[len - 1] == '\n') {
106 server_name[len - 1] = 0;
108 afs_server = server_name;
110 th = gethostbyname(afs_server);
112 printf("host %s not found; %s call aborted\n", afs_server, syscall);
115 memcpy(&hostAddr, th->h_addr, sizeof(hostAddr));
120 /* Does the actual RX connection to the afs server */
121 struct rx_connection *
122 rx_connection(afs_int32 * errorcode, char *syscall)
124 struct rx_connection *conn;
125 struct rx_securityClass *null_securityObject;
128 if (!(host = GetAfsServerAddr(syscall))) {
130 return (struct rx_connection *)0;
132 *errorcode = rx_Init(0);
134 printf("Rx initialize failed \n");
135 return (struct rx_connection *)0;
137 null_securityObject = rxnull_NewClientSecurityObject();
139 rx_NewConnection(host, htons(AFSCONF_RMTSYSPORT), RMTSYS_SERVICEID,
140 null_securityObject, 0);
142 printf("Unable to make a new connection\n");
144 return (struct rx_connection *)0;
150 /* WARNING: The calling program (i.e. klog) MUST be suid-root since we need to
151 * do a setgroups(2) call with the new pag.... */
153 #pragma weak setpag = afs_setpag
161 struct rx_connection *conn;
163 afs_int32 errorcode, errornumber, newpag, ngroups, j;
164 afs_uint32 groups[NGROUPS_MAX];
166 if (!(conn = rx_connection(&errorcode, "setpag"))) {
167 /* Remote call can't be performed for some reason.
168 * Try the local 'setpag' system call ... */
169 errorcode = lsetpag();
172 ngroups = SetClientCreds(&creds, groups);
173 errorcode = RMTSYS_SetPag(conn, &creds, &newpag, &errornumber);
177 printf("Warning: Remote setpag to %s has failed (err=%d)...\n",
183 if (afs_get_pag_from_groups(groups[0], groups[1]) == NOPAG) {
184 /* we will have to shift grouplist to make room for pag */
185 if (ngroups + 2 > NGROUPS_MAX) {
186 /* this is what the real setpag returns */
190 for (j = ngroups - 1; j >= 0; j--) {
191 groups[j + 2] = groups[j];
195 afs_get_groups_from_pag(newpag, &groups[0], &groups[1]);
196 if (setgroups(ngroups, groups) == -1) {
200 errorcode = setuid(getuid());
202 errorcode = setreuid(-1, getuid());
203 #endif /* AFS_HPUX_ENV */
208 /* Remote pioctl(2) client routine */
210 #pragma weak pioctl = afs_pioctl
212 afs_pioctl(char *path, afs_int32 cmd, struct ViceIoctl *data,
216 pioctl(char *path, afs_int32 cmd, struct ViceIoctl *data, afs_int32 follow)
219 struct rx_connection *conn;
221 afs_int32 errorcode, errornumber, ins = data->in_size;
222 afs_uint32 groups[NGROUPS_MAX];
223 rmtbulk InData, OutData;
224 char pathname[256], *pathp = pathname, *inbuffer;
225 if (!(conn = rx_connection(&errorcode, "pioctl"))) {
226 /* Remote call can't be performed for some reason.
227 * Try the local 'pioctl' system call ... */
228 errorcode = lpioctl(path, cmd, (char *)data, follow);
231 (void)SetClientCreds(&creds, groups);
236 if (!(inbuffer = (char *)malloc(ins)))
237 return (-1); /* helpless here */
239 memcpy(inbuffer, data->in, data->in_size);
240 InData.rmtbulk_len = data->in_size;
241 InData.rmtbulk_val = inbuffer;
242 inparam_conversion(cmd, InData.rmtbulk_val, 0);
244 OutData.rmtbulk_len = MAXBUFFERLEN * sizeof(*OutData.rmtbulk_val);
245 OutData.rmtbulk_val = malloc(OutData.rmtbulk_len);
246 if (!OutData.rmtbulk_val) {
251 /* We always need to pass absolute pathnames to the remote pioctl since we
252 * lose the current directory value when doing an rpc call. Below we
253 * prepend the current absolute path directory, if the name is relative */
256 /* assuming relative path name */
257 if (getcwd(pathname, 256) == NULL) {
259 printf("getwd failed; exiting\n");
262 strcpy(pathname + strlen(pathname), "/");
263 strcat(pathname, path);
265 strcpy(pathname, path);
268 /* Special meaning for a "NULL" pathname since xdr_string hates nil
269 * pointers, at least on non-RTS; of course the proper solution would
270 * be to change the interface declartion. */
271 strcpy(pathname, NIL_PATHP);
274 RMTSYS_Pioctl(conn, &creds, pathp, cmd, follow, &InData, &OutData,
278 errorcode = -1; /* Necessary since errorcode is 0 on
279 * standard remote pioctl errors */
280 if (errno != EDOM && errno != EACCES)
281 printf("Warning: Remote pioctl to %s has failed (err=%d)...\n",
285 /* Do the conversions back to the host order; store the results back
286 * on the same buffer */
287 if (data->out_size < OutData.rmtbulk_len) {
291 memcpy(data->out, OutData.rmtbulk_val, data->out_size);
292 outparam_conversion(cmd, data->out, 1);
295 free(OutData.rmtbulk_val);
302 afs_get_pag_from_groups(afs_uint32 g0, afs_uint32 g1)
304 afs_uint32 h, l, result;
308 if (g0 < 0xc000 && g1 < 0xc000) {
309 l = ((g0 & 0x3fff) << 14) | (g1 & 0x3fff);
311 h = (g1 >> 14) + h + h + h;
312 result = ((h << 28) | l);
313 /* Additional testing */
314 if (((result >> 24) & 0xff) == 'A')
323 afs_get_groups_from_pag(afs_uint32 pag, afs_uint32 * g0p, afs_uint32 * g1p)
325 unsigned short g0, g1;
328 g0 = 0x3fff & (pag >> 14);
330 g0 |= ((pag >> 28) / 3) << 14;
331 g1 |= ((pag >> 28) % 3) << 14;
338 SetClientCreds(struct clientcred *creds, afs_uint32 * groups)
342 creds->uid = getuid();
343 groups[0] = groups[1] = 0;
344 ngroups = getgroups(NGROUPS_MAX, groups);
345 creds->group0 = groups[0];
346 creds->group1 = groups[1];