1*45190Ssklower /*
2*45190Ssklower * Print the kernel X.25 accounting file, in the following format:
3*45190Ssklower * month
4*45190Ssklower * day
5*45190Ssklower * hour:min - call start time
6*45190Ssklower * duration - call duration in seconds
7*45190Ssklower * user - name of user who placed the call
8*45190Ssklower * in/out - incoming or outgoing call flag
9*45190Ssklower * address - X.121 address
10*45190Ssklower * host - host name associated with address, if known
11*45190Ssklower * rev/--- - reverse charge flag
12*45190Ssklower * packet size - packet size in bytes
13*45190Ssklower * user data - 4 bytes of user data (protocol),
14*45190Ssklower * ITI calls appear as x29d, EAN 1&2 as ean1/ean2,
15*45190Ssklower * others as 4 hex digits.
16*45190Ssklower * packets sent
17*45190Ssklower * packets received - number of packets sent and received.
18*45190Ssklower *
19*45190Ssklower * Not the nicest format for people, but it is assumed that the
20*45190Ssklower * output will be further processed before people see it.
21*45190Ssklower * The idea here is to convert the raw data to a form
22*45190Ssklower * convenient for shell or awk scripts.
23*45190Ssklower */
24*45190Ssklower #include <stdio.h>
25*45190Ssklower #include <sys/file.h>
26*45190Ssklower #include <sys/types.h>
27*45190Ssklower #include <sys/time.h>
28*45190Ssklower #include <pwd.h>
29*45190Ssklower #include <netccitt/x25.h>
30*45190Ssklower #include <netccitt/x25acct.h>
31*45190Ssklower #include <netdb.h>
32*45190Ssklower
main(argc,argv)33*45190Ssklower main(argc, argv)
34*45190Ssklower char **argv;
35*45190Ssklower {
36*45190Ssklower struct passwd *pw;
37*45190Ssklower char *user, ubuf[20], *dayt, *filename;
38*45190Ssklower FILE *fp;
39*45190Ssklower struct x25acct ac;
40*45190Ssklower char addr[16+1];
41*45190Ssklower char *format_udata();
42*45190Ssklower struct hostent *hp, *getx25hostbyaddr();
43*45190Ssklower
44*45190Ssklower if (argc > 2) {
45*45190Ssklower fprintf(stderr, "usage: %s [file]\n", argv[0]);
46*45190Ssklower exit(1);
47*45190Ssklower }
48*45190Ssklower filename = argc == 2 ? argv[1] : X25ACCTF;
49*45190Ssklower if ((fp = fopen(filename, "r")) == NULL) {
50*45190Ssklower fprintf(stderr, "%s: ", argv[0]);
51*45190Ssklower perror(filename);
52*45190Ssklower exit(1);
53*45190Ssklower }
54*45190Ssklower setx25hostent(1); /* don't close after each call */
55*45190Ssklower while (fread((char *)&ac, sizeof ac, 1, fp) == 1) {
56*45190Ssklower if (ac.x25acct_txcnt == 0 && ac.x25acct_rxcnt == 0)
57*45190Ssklower continue;
58*45190Ssklower if ((pw = getpwuid(ac.x25acct_uid)) == NULL) {
59*45190Ssklower fprintf(stderr, "%s: unknown uid: %d\n",
60*45190Ssklower argv[0], ac.x25acct_uid);
61*45190Ssklower sprintf(ubuf, "#%d", ac.x25acct_uid);
62*45190Ssklower user = ubuf;
63*45190Ssklower }
64*45190Ssklower else
65*45190Ssklower user = pw->pw_name;
66*45190Ssklower dayt = ctime(&ac.x25acct_stime);
67*45190Ssklower dayt[16] = '\0'; /* we probably know what year it is */
68*45190Ssklower dayt += 4; /* skip the day */
69*45190Ssklower
70*45190Ssklower if (ac.x25acct_addrlen > 16) {
71*45190Ssklower fprintf(stderr, "%s: Invalid addrlen %d\n",
72*45190Ssklower argv[0], ac.x25acct_addrlen);
73*45190Ssklower continue;
74*45190Ssklower }
75*45190Ssklower /*
76*45190Ssklower * Convert bcd address to ascii.
77*45190Ssklower */
78*45190Ssklower bzero(addr, sizeof addr);
79*45190Ssklower from_bcd(addr, (u_char *)ac.x25acct_addr,
80*45190Ssklower (int)ac.x25acct_addrlen);
81*45190Ssklower hp = getx25hostbyaddr(addr);
82*45190Ssklower
83*45190Ssklower printf("%s %4d %-8s %s %-14s %-9s %s %3d %-4s %3ld %3ld\n",
84*45190Ssklower dayt,
85*45190Ssklower ac.x25acct_etime,
86*45190Ssklower user,
87*45190Ssklower ac.x25acct_callin ? "in " : "out",
88*45190Ssklower addr,
89*45190Ssklower hp ? hp->h_name : addr,
90*45190Ssklower /* REVERSE means collect (by default caller pays) */
91*45190Ssklower ac.x25acct_revcharge ? "rev" : "---",
92*45190Ssklower 1 << ac.x25acct_psize,
93*45190Ssklower format_udata(ac.x25acct_udata),
94*45190Ssklower ac.x25acct_txcnt,
95*45190Ssklower ac.x25acct_rxcnt);
96*45190Ssklower }
97*45190Ssklower exit(0);
98*45190Ssklower }
99*45190Ssklower
100*45190Ssklower char *
format_udata(udata)101*45190Ssklower format_udata(udata)
102*45190Ssklower char *udata;
103*45190Ssklower {
104*45190Ssklower static char buf[15];
105*45190Ssklower
106*45190Ssklower if (bcmp(udata, "\1\0\0\0", 4) == 0)
107*45190Ssklower return "x29d";
108*45190Ssklower if (bcmp(udata, "ean", 3) == 0)
109*45190Ssklower return udata;
110*45190Ssklower sprintf(buf, "%x.%x.%x.%x",
111*45190Ssklower udata[0], udata[1], udata[2], udata[3]);
112*45190Ssklower return buf;
113*45190Ssklower }
114*45190Ssklower
from_bcd(a,x,len)115*45190Ssklower from_bcd (a, x, len)
116*45190Ssklower register char *a;
117*45190Ssklower register u_char *x;
118*45190Ssklower register int len;
119*45190Ssklower {
120*45190Ssklower register int posn = 0;
121*45190Ssklower
122*45190Ssklower while (--len >= 0) {
123*45190Ssklower if (posn++ & 0x01)
124*45190Ssklower *a = *x++ & 0x0f;
125*45190Ssklower else
126*45190Ssklower *a = (*x >> 4) & 0x0f;
127*45190Ssklower *a++ |= 0x30;
128*45190Ssklower }
129*45190Ssklower }
130