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>
26 #include "sys_prototypes.h"
29 #define NOPAG 0xffffffff /* Also defined in afs/afs.h */
30 static afs_int32 hostAddr
= 0;
31 static int hostAddrLookup
= 0;
32 char *afs_server
= 0, server_name
[128];
33 static afs_int32
SetClientCreds(struct clientcred
*creds
, afs_uint32
* groups
);
34 int afs_get_pag_from_groups(afs_uint32 g0
, afs_uint32 g1
);
35 void afs_get_groups_from_pag(afs_uint32 pag
, afs_uint32
* g0p
, afs_uint32
* g1p
);
37 /* Picks up the name of the remote afs client host where the rmtsys
38 * daemon resides. Since the clients may be diskless and/or readonly
39 * ones we felt it's better to rely on an shell environment
40 * (AFSSERVER) for the host name first. If that is not set, the
41 * $HOME/.AFSSERVER file is checked, otherwise the "/.AFSSERVER" is
45 GetAfsServerAddr(char *syscall
)
50 /* Take advantage of caching and assume that the remote host
51 * address won't change during a single program's invocation.
57 if (!(afs_server
= getenv("AFSSERVER"))) {
62 if (!(home_dir
= getenv("HOME"))) {
63 /* Our last chance is the "/.AFSSERVER" file */
64 fp
= fopen("/.AFSSERVER", "r");
71 len
= asprintf(&pathname
, "%s/%s", home_dir
, ".AFSSERVER");
72 if (len
< 0 || pathname
== NULL
)
74 fp
= fopen(pathname
, "r");
78 /* Our last chance is the "/.AFSSERVER" file */
79 fp
= fopen("/.AFSSERVER", "r");
85 if (fgets(server_name
, 128, fp
) != NULL
)
86 len
= strlen(server_name
);
91 if (server_name
[len
- 1] == '\n') {
92 server_name
[len
- 1] = 0;
94 afs_server
= server_name
;
96 th
= gethostbyname(afs_server
);
98 printf("host %s not found; %s call aborted\n", afs_server
, syscall
);
101 memcpy(&hostAddr
, th
->h_addr
, sizeof(hostAddr
));
106 /* Does the actual RX connection to the afs server */
107 struct rx_connection
*
108 rx_connection(afs_int32
* errorcode
, char *syscall
)
110 struct rx_connection
*conn
;
111 struct rx_securityClass
*null_securityObject
;
114 if (!(host
= GetAfsServerAddr(syscall
))) {
116 return (struct rx_connection
*)0;
118 *errorcode
= rx_Init(0);
120 printf("Rx initialize failed \n");
121 return (struct rx_connection
*)0;
123 null_securityObject
= rxnull_NewClientSecurityObject();
125 rx_NewConnection(host
, htons(AFSCONF_RMTSYSPORT
), RMTSYS_SERVICEID
,
126 null_securityObject
, RX_SECIDX_NULL
);
128 printf("Unable to make a new connection\n");
130 return (struct rx_connection
*)0;
136 /* WARNING: The calling program (i.e. klog) MUST be suid-root since we need to
137 * do a setgroups(2) call with the new pag.... */
139 #pragma weak setpag = afs_setpag
147 struct rx_connection
*conn
;
149 afs_int32 errorcode
, errornumber
, newpag
, ngroups
, j
;
150 afs_uint32 groups
[NGROUPS_MAX
];
152 if (!(conn
= rx_connection(&errorcode
, "setpag"))) {
153 /* Remote call can't be performed for some reason.
154 * Try the local 'setpag' system call ... */
155 errorcode
= lsetpag();
158 ngroups
= SetClientCreds(&creds
, groups
);
159 errorcode
= RMTSYS_SetPag(conn
, &creds
, &newpag
, &errornumber
);
163 printf("Warning: Remote setpag to %s has failed (err=%d)...\n",
169 if (afs_get_pag_from_groups(groups
[0], groups
[1]) == NOPAG
) {
170 /* we will have to shift grouplist to make room for pag */
171 if (ngroups
+ 2 > NGROUPS_MAX
) {
172 /* this is what the real setpag returns */
176 for (j
= ngroups
- 1; j
>= 0; j
--) {
177 groups
[j
+ 2] = groups
[j
];
181 afs_get_groups_from_pag(newpag
, &groups
[0], &groups
[1]);
182 if (setgroups(ngroups
, groups
) == -1) {
186 errorcode
= setuid(getuid());
188 errorcode
= setreuid(-1, getuid());
189 #endif /* AFS_HPUX_ENV */
194 /* Remote pioctl(2) client routine */
196 #pragma weak pioctl = afs_pioctl
198 afs_pioctl(char *path
, afs_int32 cmd
, struct ViceIoctl
*data
,
202 pioctl(char *path
, afs_int32 cmd
, struct ViceIoctl
*data
, afs_int32 follow
)
205 struct rx_connection
*conn
;
207 afs_int32 errorcode
, errornumber
, ins
= data
->in_size
;
208 afs_uint32 groups
[NGROUPS_MAX
];
209 rmtbulk InData
, OutData
;
210 char pathname
[256], *pathp
= pathname
, *inbuffer
;
211 if (!(conn
= rx_connection(&errorcode
, "pioctl"))) {
212 /* Remote call can't be performed for some reason.
213 * Try the local 'pioctl' system call ... */
214 errorcode
= lpioctl(path
, cmd
, data
, follow
);
217 (void)SetClientCreds(&creds
, groups
);
222 if (!(inbuffer
= malloc(ins
)))
223 return (-1); /* helpless here */
225 memcpy(inbuffer
, data
->in
, data
->in_size
);
226 InData
.rmtbulk_len
= data
->in_size
;
227 InData
.rmtbulk_val
= inbuffer
;
228 inparam_conversion(cmd
, InData
.rmtbulk_val
, 0);
230 OutData
.rmtbulk_len
= MAXBUFFERLEN
* sizeof(*OutData
.rmtbulk_val
);
231 OutData
.rmtbulk_val
= malloc(OutData
.rmtbulk_len
);
232 if (!OutData
.rmtbulk_val
) {
237 /* We always need to pass absolute pathnames to the remote pioctl since we
238 * lose the current directory value when doing an rpc call. Below we
239 * prepend the current absolute path directory, if the name is relative */
242 /* assuming relative path name */
243 if (getcwd(pathname
, 256) == NULL
) {
245 printf("getwd failed\n");
248 strcpy(pathname
+ strlen(pathname
), "/");
249 strcat(pathname
, path
);
251 strcpy(pathname
, path
);
254 /* Special meaning for a "NULL" pathname since xdr_string hates nil
255 * pointers, at least on non-RTS; of course the proper solution would
256 * be to change the interface declartion. */
257 strcpy(pathname
, NIL_PATHP
);
260 RMTSYS_Pioctl(conn
, &creds
, pathp
, cmd
, follow
, &InData
, &OutData
,
264 errorcode
= -1; /* Necessary since errorcode is 0 on
265 * standard remote pioctl errors */
266 if (errno
!= EDOM
&& errno
!= EACCES
)
267 printf("Warning: Remote pioctl to %s has failed (err=%d)...\n",
271 /* Do the conversions back to the host order; store the results back
272 * on the same buffer */
273 if (data
->out_size
< OutData
.rmtbulk_len
) {
277 memcpy(data
->out
, OutData
.rmtbulk_val
, data
->out_size
);
278 outparam_conversion(cmd
, data
->out
, 1);
281 free(OutData
.rmtbulk_val
);
288 afs_get_pag_from_groups(afs_uint32 g0
, afs_uint32 g1
)
290 afs_uint32 h
, l
, result
;
294 if (g0
< 0xc000 && g1
< 0xc000) {
295 l
= ((g0
& 0x3fff) << 14) | (g1
& 0x3fff);
297 h
= (g1
>> 14) + h
+ h
+ h
;
298 result
= ((h
<< 28) | l
);
299 /* Additional testing */
300 if (((result
>> 24) & 0xff) == 'A')
309 afs_get_groups_from_pag(afs_uint32 pag
, afs_uint32
* g0p
, afs_uint32
* g1p
)
311 unsigned short g0
, g1
;
314 g0
= 0x3fff & (pag
>> 14);
316 g0
|= ((pag
>> 28) / 3) << 14;
317 g1
|= ((pag
>> 28) % 3) << 14;
324 SetClientCreds(struct clientcred
*creds
, afs_uint32
* groups
)
328 creds
->uid
= getuid();
329 groups
[0] = groups
[1] = 0;
330 ngroups
= getgroups(NGROUPS_MAX
, groups
);
331 creds
->group0
= groups
[0];
332 creds
->group1
= groups
[1];