4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
30 #include <sys/acctctl.h>
39 static ac_resname_t ac_names
[] = {
41 * Process accounting resources
43 { AC_PROC
, AC_PROC_PID
, "pid" },
44 { AC_PROC
, AC_PROC_UID
, "uid" },
45 { AC_PROC
, AC_PROC_GID
, "gid" },
46 { AC_PROC
, AC_PROC_PROJID
, "projid" },
47 { AC_PROC
, AC_PROC_TASKID
, "taskid" },
48 { AC_PROC
, AC_PROC_CPU
, "cpu" },
49 { AC_PROC
, AC_PROC_TIME
, "time" },
50 { AC_PROC
, AC_PROC_COMMAND
, "command" },
51 { AC_PROC
, AC_PROC_TTY
, "tty" },
52 { AC_PROC
, AC_PROC_HOSTNAME
, "host" },
53 { AC_PROC
, AC_PROC_MICROSTATE
, "mstate" },
54 { AC_PROC
, AC_PROC_FLAG
, "flag" },
55 { AC_PROC
, AC_PROC_ANCPID
, "ancpid" },
56 { AC_PROC
, AC_PROC_WAIT_STATUS
, "wait-status" },
57 { AC_PROC
, AC_PROC_ZONENAME
, "zone" },
58 { AC_PROC
, AC_PROC_MEM
, "memory" },
61 * Task accounting resources
63 { AC_TASK
, AC_TASK_TASKID
, "taskid" },
64 { AC_TASK
, AC_TASK_PROJID
, "projid" },
65 { AC_TASK
, AC_TASK_CPU
, "cpu" },
66 { AC_TASK
, AC_TASK_TIME
, "time" },
67 { AC_TASK
, AC_TASK_HOSTNAME
, "host" },
68 { AC_TASK
, AC_TASK_MICROSTATE
, "mstate" },
69 { AC_TASK
, AC_TASK_ANCTASKID
, "anctaskid" },
70 { AC_TASK
, AC_TASK_ZONENAME
, "zone" },
73 * Flow accounting resources
75 { AC_FLOW
, AC_FLOW_SADDR
, "saddr" },
76 { AC_FLOW
, AC_FLOW_DADDR
, "daddr" },
77 { AC_FLOW
, AC_FLOW_SPORT
, "sport" },
78 { AC_FLOW
, AC_FLOW_DPORT
, "dport" },
79 { AC_FLOW
, AC_FLOW_PROTOCOL
, "proto" },
80 { AC_FLOW
, AC_FLOW_DSFIELD
, "dsfield" },
81 { AC_FLOW
, AC_FLOW_NBYTES
, "nbytes" },
82 { AC_FLOW
, AC_FLOW_NPKTS
, "npkts" },
83 { AC_FLOW
, AC_FLOW_CTIME
, "ctime" },
84 { AC_FLOW
, AC_FLOW_LSEEN
, "lseen" },
85 { AC_FLOW
, AC_FLOW_PROJID
, "projid" },
86 { AC_FLOW
, AC_FLOW_UID
, "uid" },
87 { AC_FLOW
, AC_FLOW_ANAME
, "action" },
90 * Net accounting resources
93 { AC_NET
, AC_NET_NAME
, "name" },
94 { AC_NET
, AC_NET_EHOST
, "ehost" },
95 { AC_NET
, AC_NET_EDEST
, "edest" },
96 { AC_NET
, AC_NET_VLAN_TPID
, "vlan_pid" },
97 { AC_NET
, AC_NET_VLAN_TCI
, "vlan_tci" },
98 { AC_NET
, AC_NET_SAP
, "sap" },
99 { AC_NET
, AC_NET_PRIORITY
, "priority" },
100 { AC_NET
, AC_NET_BWLIMIT
, "bwlimit" },
101 { AC_NET
, AC_NET_DEVNAME
, "devname" },
102 { AC_NET
, AC_NET_SADDR
, "src_ip" },
103 { AC_NET
, AC_NET_DADDR
, "dst_ip" },
104 { AC_NET
, AC_NET_SPORT
, "src_port" },
105 { AC_NET
, AC_NET_DPORT
, "dst_port" },
106 { AC_NET
, AC_NET_PROTOCOL
, "protocol" },
107 { AC_NET
, AC_NET_DSFIELD
, "dsfield" },
108 { AC_NET
, AC_NET_CURTIME
, "curtime" },
109 { AC_NET
, AC_NET_IBYTES
, "ibytes" },
110 { AC_NET
, AC_NET_OBYTES
, "obytes" },
111 { AC_NET
, AC_NET_IPKTS
, "ipkts" },
112 { AC_NET
, AC_NET_OPKTS
, "opkts" },
113 { AC_NET
, AC_NET_IERRPKTS
, "ierrpkts" },
114 { AC_NET
, AC_NET_OERRPKTS
, "oerrpkts" },
117 * These are included for compatibility with old acctadm that
118 * didn't have resource groups for individual accounting types.
119 * It was possible to have resource "pid" enabled for task
120 * accounting even though we couldn't actually track it.
122 { AC_TASK
, AC_NONE
, "pid" },
123 { AC_TASK
, AC_NONE
, "uid" },
124 { AC_TASK
, AC_NONE
, "gid" },
125 { AC_TASK
, AC_NONE
, "command" },
126 { AC_TASK
, AC_NONE
, "tty" },
127 { AC_TASK
, AC_NONE
, "flag" },
129 { AC_NONE
, AC_NONE
, NULL
}
135 static ac_group_t ac_groups
[] = {
136 { AC_PROC
, "extended",
137 { AC_PROC_PID
, AC_PROC_UID
, AC_PROC_GID
, AC_PROC_CPU
,
138 AC_PROC_TIME
, AC_PROC_COMMAND
, AC_PROC_TTY
, AC_PROC_PROJID
,
139 AC_PROC_TASKID
, AC_PROC_ANCPID
, AC_PROC_WAIT_STATUS
,
140 AC_PROC_ZONENAME
, AC_PROC_FLAG
, AC_PROC_MEM
,
141 AC_PROC_MICROSTATE
, AC_NONE
} },
143 { AC_PROC_PID
, AC_PROC_UID
, AC_PROC_GID
, AC_PROC_CPU
,
144 AC_PROC_TIME
, AC_PROC_COMMAND
, AC_PROC_TTY
, AC_PROC_FLAG
,
146 { AC_TASK
, "extended",
147 { AC_TASK_TASKID
, AC_TASK_PROJID
, AC_TASK_CPU
, AC_TASK_TIME
,
148 AC_TASK_HOSTNAME
, AC_TASK_MICROSTATE
, AC_TASK_ANCTASKID
,
149 AC_TASK_ZONENAME
, AC_NONE
} },
151 { AC_TASK_TASKID
, AC_TASK_PROJID
, AC_TASK_CPU
, AC_TASK_TIME
,
153 { AC_FLOW
, "extended",
154 { AC_FLOW_SADDR
, AC_FLOW_DADDR
, AC_FLOW_SPORT
, AC_FLOW_DPORT
,
155 AC_FLOW_PROTOCOL
, AC_FLOW_DSFIELD
, AC_FLOW_NBYTES
,
156 AC_FLOW_NPKTS
, AC_FLOW_ANAME
, AC_FLOW_CTIME
, AC_FLOW_LSEEN
,
157 AC_FLOW_PROJID
, AC_FLOW_UID
, AC_NONE
} },
159 { AC_FLOW_SADDR
, AC_FLOW_DADDR
, AC_FLOW_SPORT
, AC_FLOW_DPORT
,
160 AC_FLOW_PROTOCOL
, AC_FLOW_NBYTES
, AC_FLOW_NPKTS
, AC_FLOW_ANAME
,
162 { AC_NET
, "extended",
163 { AC_NET_NAME
, AC_NET_EHOST
, AC_NET_EDEST
, AC_NET_VLAN_TPID
,
164 AC_NET_VLAN_TCI
, AC_NET_SAP
, AC_NET_PRIORITY
,
165 AC_NET_BWLIMIT
, AC_NET_DEVNAME
, AC_NET_SADDR
, AC_NET_DADDR
,
166 AC_NET_SPORT
, AC_NET_DPORT
, AC_NET_PROTOCOL
, AC_NET_DSFIELD
,
167 AC_NET_CURTIME
, AC_NET_IBYTES
, AC_NET_OBYTES
, AC_NET_IPKTS
,
168 AC_NET_OPKTS
, AC_NET_IERRPKTS
, AC_NET_OERRPKTS
, AC_NONE
} },
170 { AC_NET_NAME
, AC_NET_DEVNAME
, AC_NET_EHOST
, AC_NET_EDEST
,
171 AC_NET_VLAN_TPID
, AC_NET_VLAN_TCI
, AC_NET_SAP
,
172 AC_NET_PRIORITY
, AC_NET_BWLIMIT
, AC_NET_CURTIME
, AC_NET_IBYTES
,
173 AC_NET_OBYTES
, AC_NET_IPKTS
, AC_NET_OPKTS
, AC_NET_IERRPKTS
,
174 AC_NET_OERRPKTS
, AC_NONE
} },
180 * this function returns the id of the named resource
183 name2id(char *name
, int type
)
185 ac_resname_t
*acname
= ac_names
;
186 while (acname
->ar_type
!= AC_NONE
) {
187 if (acname
->ar_type
== type
&&
188 strcmp(acname
->ar_name
, name
) == 0) {
189 if (acname
->ar_id
== AC_NONE
)
191 * For compatibility with older versions.
195 return (acname
->ar_id
);
203 * this function gives name of the resource by its id
206 id2name(int id
, int type
)
208 ac_resname_t
*acname
= ac_names
;
209 while (acname
->ar_id
!= AC_NONE
) {
210 if (acname
->ar_type
== type
&&
212 return (acname
->ar_name
);
223 for (g
= 0; ac_groups
[g
].ag_type
!= AC_NONE
; g
++) {
224 if (ac_groups
[g
].ag_type
!= type
)
226 (void) printf("%-9s", ac_groups
[g
].ag_name
);
227 (void) printf("%s", id2name(ac_groups
[g
].ag_mem
[0], type
));
228 for (r
= 1; (id
= ac_groups
[g
].ag_mem
[r
]) != AC_NONE
; r
++)
229 (void) printf(",%s", id2name(id
, type
));
236 * this function prints the list of resource groups and their members
239 printgroups(int type
)
243 if ((type
& AC_PROC
) && (type
& AC_TASK
) && (type
& AC_FLOW
) &&
247 if (type
& AC_PROC
) {
249 (void) printf("process:\n");
252 if (type
& AC_TASK
) {
254 (void) printf("task:\n");
257 if (type
& AC_FLOW
) {
259 (void) printf("flow:\n");
264 (void) printf("net:\n");
270 * this function sets the state of the particular resource
273 resset(ac_res_t
*res
, int id
, int state
)
276 resp
= (ac_res_t
*)((uintptr_t)res
+ (sizeof (ac_res_t
) * (id
- 1)));
277 resp
->ar_state
= state
;
282 * this function gets the state of the particular resource
285 resget(ac_res_t
*res
, int id
)
288 resp
= (ac_res_t
*)((uintptr_t)res
+ (sizeof (ac_res_t
) * (id
- 1)));
289 return (resp
->ar_state
);
293 * this function converts a string of resources into a buffer which then
294 * can be used for acctctl() system call
297 str2buf(ac_res_t
*buf
, char *str
, int state
, int type
)
302 if (strcmp(str
, AC_STR_NONE
) == 0)
305 * Take a lap through str, processing resources, modifying buf copy
306 * as appropriate and making sure that all resource names are valid.
308 if ((copy
= malloc(strlen(str
) + 1)) == NULL
)
309 die(gettext("not enough memory\n"));
310 (void) memcpy(copy
, str
, strlen(str
) + 1);
311 p
= strtok(copy
, ", ");
314 * check if str contains any resource groups
316 for (ok
= 0, i
= 0; (g
= ac_groups
[i
].ag_name
) != NULL
; i
++) {
317 if (strcmp(p
, g
) == 0 && ac_groups
[i
].ag_type
== type
) {
318 for (j
= 0; (id
= ac_groups
[i
].ag_mem
[j
]) !=
320 resset(buf
, id
, state
);
326 id
= name2id(p
, type
);
328 resset(buf
, id
, state
);
330 die(gettext("unknown %s resource: %s\n"),
331 ac_type_name(type
), p
);
333 p
= strtok(NULL
, ", ");
339 * this function converts a buffer into a string of resource names.
340 * state (on/off) for resources of interest is selected by the third argument.
341 * accounting type is selected by the fourth argument.
342 * it is caller's responsibility to free the allocated string buffer.
345 buf2str(ac_res_t
*buffer
, size_t bufsz
, int state
, int type
)
351 if ((buf
= malloc(bufsz
)) == NULL
||
352 (str
= malloc(MAXRESLEN
)) == NULL
)
353 die(gettext("not enough memory\n"));
354 (void) memset(str
, 0, MAXRESLEN
);
355 (void) memcpy(buf
, buffer
, bufsz
);
357 * check if buf has any resource groups in it
359 for (i
= 0; (g
= ac_groups
[i
].ag_name
) != NULL
; i
++) {
360 if (ac_groups
[i
].ag_type
!= type
)
362 for (j
= 0; (id
= ac_groups
[i
].ag_mem
[j
]) != AC_NONE
; j
++) {
364 if (resget(buf
, id
) != state
) {
369 if (ok
) { /* buf contains this resource group */
370 if (strlen(str
) != 0)
371 (void) strcat(str
, ",");
372 (void) strcat(str
, g
);
373 for (j
= 0; (id
= ac_groups
[i
].ag_mem
[j
]) != AC_NONE
;
376 state
== AC_ON
? AC_OFF
: AC_ON
);
381 * browse through the rest of the buf for all remaining resources
382 * that are not a part of any groups
384 for (cur
= buf
; cur
->ar_id
!= AC_NONE
; cur
++) {
385 if (cur
->ar_state
== state
) {
386 if (strlen(str
) != 0)
387 (void) strcat(str
, ",");
388 if (id2name(cur
->ar_id
, type
) == NULL
)
389 die(gettext("unknown %s resource id (%d)\n"),
390 ac_type_name(type
), cur
->ar_id
);
391 (void) strcat(str
, id2name(cur
->ar_id
, type
));
394 if (strlen(str
) == 0)
395 (void) strcpy(str
, AC_STR_NONE
);