OPENAFS-SA-2018-001 Add auditing to butc server RPC implementations
[openafs.git] / src / butc / tcstatus.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 <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <roken.h>
14
15 #include <afs/com_err.h>
16 #include <lock.h>
17 #include <afs/bubasics.h>
18 #include <afs/tcdata.h>
19 #include <afs/butc.h>
20 #include <afs/budb_client.h>
21 #include <afs/bucoord_prototypes.h>
22
23 #include "butc_internal.h"
24 #include "error_macros.h"
25 #include "butc_xbsa.h"
26 #include "afs/audit.h"
27
28 /* tape coordinator - task status management */
29 extern afs_int32 xbsaType;
30
31 dlqlinkT statusHead;
32 struct Lock statusQueueLock;
33 struct Lock cmdLineLock;
34
35 static afs_int32 SGetStatus(struct rx_call *call, afs_uint32 taskId,
36                             struct tciStatusS *statusPtr);
37 static afs_int32 SEndStatus(struct rx_call *call, afs_uint32 taskId);
38 static afs_int32 SRequestAbort(struct rx_call *call, afs_uint32 taskId);
39 static afs_int32 SScanStatus(struct rx_call *call, afs_uint32 *taskId,
40                              struct tciStatusS *statusPtr, afs_uint32 *flags);
41
42 /* STC_GetStatus
43  *      get the status of a task
44  * entry:
45  *      taskId - task for which status required
46  * exit:
47  *      statusPtr - filled in with task status
48  */
49
50 afs_int32
51 STC_GetStatus(struct rx_call *call, afs_uint32 taskId,
52               struct tciStatusS *status)
53 {
54     afs_int32 code;
55
56     code = SGetStatus(call, taskId, status);
57     osi_auditU(call, TC_GetStatusEvent, code,
58                AUD_INT, taskId, AUD_TSTT, status, AUD_END);
59     return code;
60 }
61
62 static afs_int32
63 SGetStatus(struct rx_call *call, afs_uint32 taskId,
64            struct tciStatusS *statusPtr)
65 {
66     statusP ptr;
67     int retval = 0;
68
69     memset(statusPtr, 0, sizeof(*statusPtr));
70     if (callPermitted(call) == 0)
71         return (TC_NOTPERMITTED);
72
73     lock_Status();
74     ptr = findStatus(taskId);
75     if (ptr) {
76         strcpy(statusPtr->taskName, ptr->taskName);
77         strcpy(statusPtr->volumeName, ptr->volumeName);
78         statusPtr->taskId = ptr->taskId;
79         statusPtr->flags = ptr->flags;
80         statusPtr->nKBytes = ptr->nKBytes;
81         statusPtr->dbDumpId = ptr->dbDumpId;
82         statusPtr->lastPolled = ptr->lastPolled;
83         statusPtr->volsFailed = ptr->volsFailed;
84         ptr->lastPolled = time(0);
85     } else
86         retval = TC_NODENOTFOUND;
87     unlock_Status();
88
89     return (retval);
90 }
91
92 afs_int32
93 STC_EndStatus(struct rx_call *call, afs_uint32 taskId)
94 {
95     afs_int32 code;
96
97     code = SEndStatus(call, taskId);
98     osi_auditU(call, TC_EndStatusEvent, code, AUD_INT, taskId, AUD_END);
99     return code;
100 }
101
102 static afs_int32
103 SEndStatus(struct rx_call *call, afs_uint32 taskId)
104 {
105     statusP ptr;
106     int retval = 0;
107
108     if (callPermitted(call) == 0)
109         return (TC_NOTPERMITTED);
110
111     lock_Status();
112     ptr = findStatus(taskId);
113     unlock_Status();
114
115     if (ptr)
116         deleteStatusNode(ptr);
117     else
118         retval = TC_NODENOTFOUND;
119
120     return (retval);
121 }
122
123 afs_int32
124 STC_RequestAbort(struct rx_call *call, afs_uint32 taskId)
125 {
126     afs_int32 code;
127
128     code = SRequestAbort(call, taskId);
129     osi_auditU(call, TC_RequestAbortEvent, code, AUD_INT, taskId, AUD_END);
130     return code;
131 }
132
133 static afs_int32
134 SRequestAbort(struct rx_call *call, afs_uint32 taskId)
135 {
136     statusP ptr;
137     int retval = 0;
138
139     if (callPermitted(call) == 0)
140         return (TC_NOTPERMITTED);
141
142     lock_Status();
143     ptr = findStatus(taskId);
144     if (ptr)
145         ptr->flags |= ABORT_REQUEST;
146     else
147         retval = TC_NODENOTFOUND;
148     unlock_Status();
149     return (retval);
150 }
151
152 /* STC_ScanStatus
153  *      Get status of all tasks on the butc, successively. Initial call
154  *      should come in with TSK_STAT_FIRST flag set to initialize the
155  *      scan.
156  * entry:
157  *      taskId - specifies the task whose status is to be returned
158  *              (unless TSK_STAT_FIRST set in which case it is ignored)
159  * exit:
160  *      taskId - id of next task in the list
161  *      flags - TSK_STAT_END will be set when one reaches the end of
162  *              the task list. taskId is not updated in this case.
163  * return values:
164  *      0 - normal
165  *      TC_NOTASKS - no tasks active
166  */
167
168 afs_int32
169 STC_ScanStatus(struct rx_call *call, afs_uint32 *taskId,
170                struct tciStatusS *status, afs_uint32 *flags)
171 {
172     afs_int32 code;
173
174     code = SScanStatus(call, taskId, status, flags);
175     osi_auditU(call, TC_ScanStatusEvent, code,
176                AUD_INT, *taskId, AUD_TSTT, status, AUD_INT, *flags, AUD_END);
177     return code;
178 }
179
180 static afs_int32
181 SScanStatus(struct rx_call *call, afs_uint32 *taskId,
182             struct tciStatusS *statusPtr, afs_uint32 *flags)
183 {
184     statusP ptr = 0;
185     dlqlinkP dlqPtr;
186
187     memset(statusPtr, 0, sizeof(*statusPtr));
188     if (callPermitted(call) == 0)
189         return (TC_NOTPERMITTED);
190
191     lock_Status();
192
193     if (CONF_XBSA)
194         *flags |= TSK_STAT_XBSA;
195     if (xbsaType == XBSA_SERVER_TYPE_ADSM)
196         *flags |= TSK_STAT_ADSM;
197
198     if (*flags & TSK_STAT_FIRST) {
199         /* find first status node */
200         dlqPtr = statusHead.dlq_next;
201         if (dlqPtr == &statusHead) {
202             /* no status nodes */
203             *flags |= (TSK_STAT_NOTFOUND | TSK_STAT_END);
204             unlock_Status();
205             return (0);
206         }
207         ptr = (statusP) dlqPtr;
208     } else {
209         ptr = findStatus(*taskId);
210         if (ptr == 0) {
211             /* in the event that the set of tasks has changed, just
212              * finish, letting the caller retry
213              */
214
215             *flags |= (TSK_STAT_NOTFOUND | TSK_STAT_END);
216             unlock_Status();
217             return (0);
218         }
219     }
220
221     /* ptr is now set to the status node we wish to return. Determine
222      * what the next node will be
223      */
224
225     if (ptr->link.dlq_next == &statusHead)
226         *flags |= TSK_STAT_END;
227     else
228         *taskId = ((statusP) ptr->link.dlq_next)->taskId;
229
230     strcpy(statusPtr->taskName, ptr->taskName);
231     strcpy(statusPtr->volumeName, ptr->volumeName);
232     statusPtr->taskId = ptr->taskId;
233     statusPtr->flags = ptr->flags;
234     statusPtr->nKBytes = ptr->nKBytes;
235     statusPtr->lastPolled = ptr->lastPolled;
236
237     unlock_Status();
238     return (0);
239 }
240
241
242 /* ---------------------------------
243  * misc. status management routines
244  * ---------------------------------
245  */
246
247 /* checkAbortByTaskId
248  * exit:
249  *      0 - continue
250  *      n - abort requested
251  */
252
253 int
254 checkAbortByTaskId(afs_uint32 taskId)
255 {
256     statusP statusPtr;
257     int retval = 0;
258
259     lock_Status();
260     statusPtr = findStatus(taskId);
261     if (statusPtr) {
262         retval = statusPtr->flags & ABORT_REQUEST;
263     }
264     unlock_Status();
265     return (retval);
266 }
267
268 /* getStatusFlag
269  *      For backwards compatibility. Queries flag status
270  * exit:
271  *      0 - flag clear
272  *      n - flag set
273  */
274
275 afs_uint32
276 getStatusFlag(afs_uint32 taskId, afs_uint32 flag)
277 {
278     statusP statusPtr;
279     int retval = 0;
280
281     lock_Status();
282     statusPtr = findStatus(taskId);
283     if (statusPtr) {
284         retval = statusPtr->flags & flag;
285     }
286     unlock_Status();
287     return (retval);
288 }