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