2 * (C) COPYRIGHT IBM CORPORATION 1987, 1988
3 * LICENSED MATERIALS - PROPERTY OF IBM
7 * This module (residing in lib/afs/librmtsys.a) implements the client side of
8 * the rpc version (via rx) of non-standard system calls. Currently only rpc
9 * calls of setpag, and pioctl are supported.
11 #include <afs/param.h>
14 #include <sys/types.h>
20 #include <netinet/in.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];
34 static afs_int32 SetClientCreds();
36 /* Picks up the name of the remote afs client host where the rmtsys
37 * daemon resides. Since the clients may be diskless and/or readonly
38 * ones we felt it's better to rely on an shell environment
39 * (AFSSERVER) for the host name first. If that is not set, the
40 * $HOME/.AFSSERVER file is checked, otherwise the "/.AFSSERVER" is
43 afs_int32 GetAfsServerAddr(syscall)
46 register struct hostent *th;
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");
68 fgets(server_name, 128, fp);
73 sprintf(pathname, "%s/%s", home_dir, ".AFSSERVER");
74 fp = fopen(pathname, "r");
76 /* Our last chance is the "/.AFSSERVER" file */
77 fp = fopen("/.AFSSERVER", "r");
82 fgets(server_name, 128, fp);
85 len = strlen(server_name);
89 if (server_name[len-1] == '\n') {
90 server_name[len-1] = 0;
92 afs_server = server_name;
94 th = gethostbyname(afs_server);
96 printf("host %s not found; %s call aborted\n", afs_server, syscall);
99 bcopy(th->h_addr, &hostAddr, sizeof(hostAddr));
104 /* Does the actual RX connection to the afs server */
105 struct rx_connection *rx_connection(errorcode, syscall)
106 afs_int32 *errorcode;
109 struct rx_connection *conn;
110 struct rx_securityClass *null_securityObject;
112 if (!(host = GetAfsServerAddr(syscall))) {
114 return (struct rx_connection *)0;
116 *errorcode = rx_Init(0);
118 printf("Rx initialize failed \n");
119 return (struct rx_connection *)0;
121 null_securityObject = rxnull_NewClientSecurityObject();
122 conn = rx_NewConnection(host, htons(AFSCONF_RMTSYSPORT), RMTSYS_SERVICEID, null_securityObject, 0);
124 printf("Unable to make a new connection\n");
126 return (struct rx_connection *)0;
132 /* WARNING: The calling program (i.e. klog) MUST be suid-root since we need to
133 * do a setgroups(2) call with the new pag.... */
135 #pragma weak setpag = afs_setpag
141 struct rx_connection *conn;
143 afs_int32 errorcode, errornumber, newpag, ngroups, j, groups[NGROUPS_MAX];
145 if (!(conn = rx_connection(&errorcode, "setpag"))) {
146 /* Remote call can't be performed for some reason.
147 * Try the local 'setpag' system call ... */
148 errorcode = lsetpag();
151 ngroups = SetClientCreds(&creds, groups);
152 errorcode = RMTSYS_SetPag(conn, &creds, &newpag, &errornumber);
156 printf("Warning: Remote setpag to %s has failed (err=%d)...\n",
162 if (afs_get_pag_from_groups(groups[0], groups[1]) == NOPAG) {
163 /* we will have to shift grouplist to make room for pag */
164 if (ngroups + 2 > NGROUPS_MAX) {
165 /* this is what the real setpag returns */
169 for (j = ngroups - 1; j >= 0; j--) {
170 groups[j + 2] = groups[j];
174 afs_get_groups_from_pag(newpag, &groups[0], &groups[1]);
175 if (setgroups(ngroups, groups) == -1) {
179 errorcode = setuid(getuid());
181 errorcode = setreuid(-1, getuid());
182 #endif /* AFS_HPUX_ENV */
187 /* Remote pioctl(2) client routine */
189 #pragma weak pioctl = afs_pioctl
190 int afs_pioctl(path, cmd, data, follow)
192 int pioctl(path, cmd, data, follow)
195 afs_int32 cmd, follow;
196 struct ViceIoctl *data;
198 struct rx_connection *conn;
200 afs_int32 errorcode, groups[NGROUPS_MAX], errornumber, ins= data->in_size;
201 rmtbulk InData, OutData;
202 char pathname[256], *pathp = pathname, *inbuffer;
203 extern char *getwd();
204 if (!(conn = rx_connection(&errorcode, "pioctl"))) {
205 /* Remote call can't be performed for some reason.
206 * Try the local 'pioctl' system call ... */
207 errorcode = lpioctl(path, cmd, data, follow);
210 (void) SetClientCreds(&creds, groups);
214 if (!(inbuffer = (char *)malloc(ins)))
215 return (-1); /* helpless here */
217 bcopy(data->in, inbuffer, data->in_size);
218 InData.rmtbulk_len = data->in_size;
219 InData.rmtbulk_val = inbuffer;
220 inparam_conversion(cmd, InData.rmtbulk_val, 0);
221 OutData.rmtbulk_len = data->out_size;
222 OutData.rmtbulk_val = data->out;
223 /* We always need to pass absolute pathnames to the remote pioctl since we
224 * lose the current directory value when doing an rpc call. Below we
225 * prepend the current absolute path directory, if the name is relative */
228 /* assuming relative path name */
229 if (getwd(pathname) == NULL) {
231 printf("getwd failed; exiting\n");
234 strcpy(pathname+strlen(pathname), "/");
235 strcat(pathname, path);
237 strcpy(pathname, path);
240 /* Special meaning for a "NULL" pathname since xdr_string hates nil
241 * pointers, at least on non-RTS; of course the proper solution would
242 * be to change the interface declartion. */
243 strcpy(pathname, NIL_PATHP);
245 errorcode = RMTSYS_Pioctl(conn, &creds, pathp, cmd, follow, &InData,
246 &OutData, &errornumber);
249 errorcode = -1; /* Necessary since errorcode is 0 on
250 * standard remote pioctl errors */
251 if (errno != EDOM && errno != EACCES)
252 printf("Warning: Remote pioctl to %s has failed (err=%d)...\n",
256 /* Do the conversions back to the host order; store the results back
257 * on the same buffer */
258 outparam_conversion(cmd, OutData.rmtbulk_val, 1);
265 int afs_get_pag_from_groups(g0, g1)
268 afs_uint32 h, l, result;
272 if (g0 < 0xc000 && g1 < 0xc000) {
273 l = ((g0 & 0x3fff) << 14) | (g1 & 0x3fff);
275 h = (g1 >> 14) + h + h + h;
276 result = ((h << 28) | l);
277 /* Additional testing */
278 if (((result >> 24) & 0xff) == 'A')
287 afs_get_groups_from_pag(pag, g0p, g1p)
289 afs_uint32 *g0p, *g1p;
291 unsigned short g0, g1;
294 g0 = 0x3fff & (pag >> 14);
296 g0 |= ((pag >> 28) / 3) << 14;
297 g1 |= ((pag >> 28) % 3) << 14;
303 static afs_int32 SetClientCreds(creds, groups)
304 struct clientcred *creds;
309 creds->uid = getuid();
310 groups[0] = groups[1] = 0;
311 ngroups = getgroups(NGROUPS_MAX, groups);
312 creds->group0 = groups[0];
313 creds->group1 = groups[1];