cmd: avoid piggy-backing flags in the help string
[openafs.git] / src / venus / cacheout.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
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
8  */
9
10
11 #include <afsconfig.h>
12 #include <afs/param.h>
13
14 #include <roken.h>
15
16 #include <ctype.h>
17
18 #include <afs/auth.h>
19 #include <afs/cmd.h>
20 #include <afs/cellconfig.h>
21 #include <afs/afsint.h>
22 #include <afs/vlserver.h>
23 #include <rx/rx.h>
24 #include <rx/xdr.h>
25 #include <ubik.h>
26 #include <afs/kauth.h>
27 #include <afs/afsutil.h>
28 #include <afs/vldbint.h>
29
30 /*
31 File servers in NW byte order.
32 */
33
34 static afs_int32 server_count = 0;
35 static afs_int32 server_id[256];
36
37 static struct ubik_client *client;
38
39 static struct rx_securityClass *sc;
40 static int scindex;
41
42 /*
43 Obtain list of file servers as known to VLDB. These may
44 not actually be configured as file servers in the cell.
45 */
46
47 static afs_int32
48 ListServers(void)
49 {
50     afs_int32 code;
51     int i;
52     struct VLCallBack vlcb;
53     struct VLCallBack spare3;
54     bulkaddrs addrs, m_addrs;
55     afs_uint32 ip;
56     afs_int32 base, index;
57     afsUUID m_uuid;
58     afs_int32 m_uniq = 0;
59     afs_int32 m_nentries;
60     char hoststr[16];
61     ListAddrByAttributes m_attrs;
62
63     memset(&addrs, 0, sizeof(addrs));
64     memset(&spare3, 0, sizeof(spare3));
65     code =
66         ubik_VL_GetAddrs(client, 0, 0, 0, &vlcb,
67                   &server_count, &addrs);
68     if (code) {
69         printf("Fatal error: could not get list of file servers\n");
70         return 1;
71     }
72
73     for (i = 0; i < server_count; ++i) {
74         ip = addrs.bulkaddrs_val[i];
75
76         if (((ip & 0xff000000) == 0xff000000) && (ip & 0xffff)) {
77             base = (ip >> 16) & 0xff;
78             index = ip & 0xffff;
79
80             /* server is a multihomed host; query the vldb for its addresses,
81              * and just pick the first one */
82
83             if ((base >= 0) && (base <= VL_MAX_ADDREXTBLKS) && (index >= 1)
84                 && (index <= VL_MHSRV_PERBLK)) {
85
86                 m_attrs.Mask = VLADDR_INDEX;
87                 m_attrs.index = (base * VL_MHSRV_PERBLK) + index;
88                 m_nentries = 0;
89                 m_addrs.bulkaddrs_val = 0;
90                 m_addrs.bulkaddrs_len = 0;
91
92                 code = ubik_VL_GetAddrsU(client, 0, &m_attrs, &m_uuid, &m_uniq,
93                                          &m_nentries, &m_addrs);
94
95                 if (code || m_addrs.bulkaddrs_len == 0) {
96                     printf("Error getting multihomed addresses for server "
97                            "%s (index %ld)\n",
98                            afs_inet_ntoa_r(m_addrs.bulkaddrs_val[0], hoststr),
99                            afs_printable_int32_ld(m_attrs.index));
100                     server_id[i] = 0;
101                 } else {
102                     server_id[i] = htonl(m_addrs.bulkaddrs_val[0]);
103                 }
104             }
105         } else {
106             server_id[i] = htonl(addrs.bulkaddrs_val[i]);
107         }
108     }
109
110     return code;
111 }
112
113
114 static int
115 InvalidateCache(struct cmd_syndesc *as, void *arock)
116 {
117     afs_int32 code = 0;
118     struct cmd_item *u;
119     struct rx_connection *conn;
120     int i;
121     afs_int32 port = 7000;
122     char hoststr[16];
123     int err = 0;
124
125     afs_int32 spare1 = 0;
126     afs_int32 spare2, spare3;
127
128     afs_int32 id[256];
129     afs_int32 ip[256];
130
131     struct ViceIds vid;
132     struct IPAddrs ipa;
133
134     code = ListServers();
135     if (code)
136         return code;
137
138
139     /* make sure something there */
140
141     if (!as->parms[0].items && !as->parms[1].items) {
142         printf("Use -help flag for list of optional argmuments\n");
143         return 1;
144     }
145
146     /* get user ids */
147
148     for (i = 0, u = as->parms[0].items; i < 255 && u; ++i, u = u->next) {
149         code = util_GetInt32(u->data, &id[i]);
150         if (code) {
151             printf("Fatal error: bad conversion to long for %s\n", u->data);
152             return code;
153         }
154     }
155
156     id[i] = 0;
157     vid.ViceIds_len = i;
158     vid.ViceIds_val = id;
159
160     /* get IP addresses, convert to NW byte order */
161
162     for (i = 0, u = as->parms[1].items; i < 255 && u; ++i, u = u->next)
163         ip[i] = inet_addr(u->data);
164
165     ip[i] = 0;
166     ipa.IPAddrs_len = i;
167     ipa.IPAddrs_val = ip;
168
169     for (i = 0; i < server_count; ++i) {
170         if (!server_id[i]) {
171             err = 1;
172             continue;
173         }
174         conn = rx_NewConnection(server_id[i], htons(port), 1, sc, scindex);
175         if (!conn) {
176             printf("Informational: could not connect to \
177 file server %s\n", afs_inet_ntoa_r(server_id[i], hoststr));
178             err = 1;
179             continue;
180         }
181
182         /* invalidate the cache */
183
184         code = RXAFS_FlushCPS(conn, &vid, &ipa, spare1, &spare2, &spare3);
185
186         /*
187          * May get spurious error codes in case server is
188          * down or is reported by VLDB as a file server
189          * even though it is not configured as such in the
190          * cell.
191          */
192
193         if (code) {
194             printf("Informational: failed to invalidate \
195 file server %s cache code = %ld\n", afs_inet_ntoa_r(server_id[i], hoststr),
196             afs_printable_int32_ld(code));
197             err = 1;
198         }
199
200         rx_DestroyConnection(conn);
201     }
202     return err;
203 }
204
205 static int
206 GetServerList(struct cmd_syndesc *as, void *arock)
207 {
208     int code;
209     int i;
210
211     code = ListServers();
212     if (code)
213         return (code);
214
215     printf("There are %d file servers in the cell\n\n", server_count);
216     fflush(stdout);
217     for (i = 0; i < server_count; ++i)
218         printf("%s\n", hostutil_GetNameByINet(server_id[i]));
219     fflush(stdout);
220
221     return code;
222 }
223
224 /*
225 User enters lists of:
226
227         1. AFS user ids - say from "pts exam username".
228         2. IP addresses - say from /etc/hosts (no wildcards).
229
230 Command is executed in user's cell.
231 */
232
233 static int
234 MyBeforeProc(struct cmd_syndesc *as, void *arock)
235 {
236     char *tcell = NULL;
237     char confdir[200];
238     struct afsconf_dir *tdir;
239     struct afsconf_cell info;
240     struct rx_connection *serverconns[MAXSERVERS];
241     afs_int32 code, i;
242     struct rx_securityClass *scnull;
243     rxkad_level sclevel = rxkad_auth;
244
245     sprintf(confdir, "%s", AFSDIR_CLIENT_ETC_DIRPATH);
246     if (as->parms[4].items) { /* -localauth */
247         sprintf(confdir, "%s", AFSDIR_SERVER_ETC_DIRPATH);
248     }
249
250     if (as->parms[5].items) { /* -encrypt */
251         sclevel = rxkad_crypt;
252     }
253
254     /* setup to talk to servers */
255     code = rx_Init(0);
256     if (code) {
257         printf("Warning: could not initialize network communication.\n");
258         return 1;
259     }
260
261     scnull = sc = rxnull_NewClientSecurityObject();
262     scindex = 0;
263
264     tdir = afsconf_Open(confdir);
265     if (!tdir) {
266         printf("Warning: could not get cell configuration.\n");
267         return 1;
268     }
269
270     if (as->parms[2].items)     /* if -cell specified */
271         tcell = as->parms[2].items->data;
272     code = afsconf_GetCellInfo(tdir, tcell, AFSCONF_VLDBSERVICE, &info);
273     if (code || info.numServers > MAXSERVERS) {
274         printf("Warning: could not init cell info.\n");
275         return 1;
276     }
277
278     if (as->parms[4].items) { /* -localauth */
279         if (sclevel == rxkad_crypt) {
280             code = afsconf_ClientAuthSecure(tdir, &sc, &scindex);
281         } else {
282             code = afsconf_ClientAuth(tdir, &sc, &scindex);
283         }
284         if (code || scindex == 0) {
285             afsconf_Close(tdir);
286             fprintf(stderr, "Could not get security object for -localauth (code: %d)\n",
287                     code);
288             return -1;
289         }
290
291     } else if (!as->parms[3].items) { /* not -noauth */
292         struct ktc_principal sname;
293         struct ktc_token ttoken;
294
295         strcpy(sname.cell, info.name);
296         sname.instance[0] = '\0';
297         strcpy(sname.name, "afs");
298
299         code = ktc_GetToken(&sname, &ttoken, sizeof(ttoken), NULL);
300         if (code) {
301             fprintf(stderr, "Could not get afs tokens, running unauthenticated\n");
302         } else {
303             scindex = 2;
304             sc = rxkad_NewClientSecurityObject(sclevel, &ttoken.sessionKey,
305                                                ttoken.kvno, ttoken.ticketLen,
306                                                ttoken.ticket);
307         }
308     }
309
310     for (i = 0; i < info.numServers; ++i)
311         serverconns[i] =
312             rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
313                              info.hostAddr[i].sin_port, USER_SERVICE_ID, scnull,
314                              0);
315     for (; i < MAXSERVERS; ++i) {
316         serverconns[i] = (struct rx_connection *)0;
317     }
318     code = ubik_ClientInit(serverconns, &client);
319     if (code) {
320         printf("Warning: could not initialize RPC interface.\n");
321         return 1;
322     }
323     return 0;
324 }
325
326
327 int
328 main(int argc, char **argv)
329 {
330     afs_int32 code = 0;
331     struct cmd_syndesc *ts;
332
333 #ifdef  AFS_AIX32_ENV
334     struct sigaction nsa;
335
336     sigemptyset(&nsa.sa_mask);
337     nsa.sa_handler = SIG_DFL;
338     nsa.sa_flags = SA_FULLDUMP;
339     sigaction(SIGSEGV, &nsa, NULL);
340 #endif
341
342     /*
343      * Look in /usr/vice/etc (client side database).
344      */
345     cmd_SetBeforeProc(MyBeforeProc, NULL);
346
347     ts = cmd_CreateSyntax("initcmd" /*"invalidatecache" */ , InvalidateCache,
348                           NULL, 0, "invalidate server ACL cache");
349     cmd_AddParm(ts, "-id", CMD_LIST, CMD_OPTIONAL, "user identifier");
350     cmd_AddParm(ts, "-ip", CMD_LIST, CMD_OPTIONAL, "IP address");
351     cmd_CreateAlias(ts, "ic");
352     cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
353     cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL, "don't authenticate");
354     cmd_AddParm(ts, "-localauth", CMD_FLAG, CMD_OPTIONAL, "user server tickets");
355     cmd_AddParm(ts, "-encrypt", CMD_FLAG, CMD_OPTIONAL, "encrypt commands");
356
357     ts = cmd_CreateSyntax("listservers", GetServerList, NULL, 0,
358                           "list servers in the cell");
359     cmd_CreateAlias(ts, "ls");
360
361     code = cmd_Dispatch(argc, argv);
362
363     rx_Finalize();
364
365     exit(code);
366 }