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