315064fd2b0e90d789d6348f8de4b210621668b8
[tac_plus.git] / acct.c
1 /* 
2    Copyright (c) 1995-1998 by Cisco systems, Inc.
3
4    Permission to use, copy, modify, and distribute this software for
5    any purpose and without fee is hereby granted, provided that this
6    copyright and permission notice appear on all copies of the
7    software and supporting documentation, the name of Cisco Systems,
8    Inc. not be used in advertising or publicity pertaining to
9    distribution of the program without specific prior permission, and
10    notice be given in supporting documentation that modification,
11    copying and distribution is by permission of Cisco Systems, Inc.
12
13    Cisco Systems, Inc. makes no representations about the suitability
14    of this software for any purpose.  THIS SOFTWARE IS PROVIDED ``AS
15    IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
16    WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17    FITNESS FOR A PARTICULAR PURPOSE.
18 */
19
20 #include "tac_plus.h"
21
22 /*
23  *  Come here when we receive an Start Accounting packet
24  */
25
26 void account();
27
28 /* For  DB accounting */
29 #ifdef DB
30 int db_acct();
31 #endif /* DB */
32
33 void
34 accounting(pak)
35 u_char *pak;
36 {
37     struct acct *acct_pak;
38     u_char *p;
39     HDR *hdr;
40     u_char *read_packet();
41     int i, len;
42
43     if (debug & DEBUG_ACCT_FLAG)
44         report(LOG_DEBUG, "Start accounting request");
45
46     hdr = (HDR *) pak;
47     acct_pak = (struct acct *) (pak + TAC_PLUS_HDR_SIZE);
48
49     /* Do some sanity checking on the packet */
50
51     /* arg counts start here */
52     p = pak + TAC_PLUS_HDR_SIZE + TAC_ACCT_REQ_FIXED_FIELDS_SIZE;
53
54     /* Length checks */
55     len = TAC_ACCT_REQ_FIXED_FIELDS_SIZE;
56     len += acct_pak->user_len + acct_pak->port_len + 
57         acct_pak->rem_addr_len + acct_pak->arg_cnt;
58     for (i = 0; i < (int)acct_pak->arg_cnt; i++) {
59         len += p[i];
60     }
61
62     if (len != ntohl(hdr->datalength)) {
63         send_error_reply(TAC_PLUS_ACCT, NULL);
64         return;
65     }
66
67     account(pak);
68
69     free(pak);
70 }
71
72 void
73 account(pak)
74 u_char *pak;
75 {
76     struct acct *acct_pak;
77     u_char *p, *argsizep;
78     struct acct_rec rec;
79     struct identity identity;
80     char **cmd_argp;
81     int i, errors, status;
82
83     acct_pak = (struct acct *) (pak + TAC_PLUS_HDR_SIZE);
84
85     /* Fill out accounting record structure */
86     bzero(&rec, sizeof(struct acct_rec));
87
88     if (acct_pak->flags & TAC_PLUS_ACCT_FLAG_WATCHDOG)
89         rec.acct_type = ACCT_TYPE_UPDATE;
90     if (acct_pak->flags & TAC_PLUS_ACCT_FLAG_START)
91         rec.acct_type = ACCT_TYPE_START;
92     if (acct_pak->flags & TAC_PLUS_ACCT_FLAG_STOP)
93         rec.acct_type = ACCT_TYPE_STOP;
94
95     rec.authen_method  = acct_pak->authen_method;
96     rec.authen_type    = acct_pak->authen_type;
97     rec.authen_service = acct_pak->authen_service;
98
99     /* start of variable length data is here */
100     p = pak + TAC_PLUS_HDR_SIZE + TAC_ACCT_REQ_FIXED_FIELDS_SIZE;
101
102     /* skip arg cnts */
103     p += acct_pak->arg_cnt;
104
105     /* zero out identity struct */
106     bzero(&identity, sizeof(struct identity));
107
108     identity.username = tac_make_string(p, (int)acct_pak->user_len);
109     p += acct_pak->user_len;
110
111     identity.NAS_name = tac_strdup(session.peer);
112
113     identity.NAS_port = tac_make_string(p, (int)acct_pak->port_len);
114     p += acct_pak->port_len;
115     if (acct_pak->port_len <= 0) {
116         strcpy(session.port, "unknown-port");
117     } else {
118         strcpy(session.port, identity.NAS_port);
119     }
120
121     identity.NAC_address = tac_make_string(p, (int)acct_pak->rem_addr_len);
122     p += acct_pak->rem_addr_len;
123
124     identity.priv_lvl = acct_pak->priv_lvl;
125
126     rec.identity = &identity;
127
128     /* Now process cmd args */
129     argsizep = pak + TAC_PLUS_HDR_SIZE + TAC_ACCT_REQ_FIXED_FIELDS_SIZE;
130
131     cmd_argp = (char **) tac_malloc(acct_pak->arg_cnt * sizeof(char *));
132
133     for (i = 0; i < (int)acct_pak->arg_cnt; i++) {
134         cmd_argp[i] = tac_make_string(p, *argsizep);
135         p += *argsizep++;
136     }
137
138     rec.args = cmd_argp;
139     rec.num_args = acct_pak->arg_cnt;
140
141 #ifdef MAXSESS
142     /*
143      * Tally for MAXSESS counting
144      */
145     loguser(&rec);
146 #endif
147
148     /*
149      * Do accounting.
150      */
151     if (wtmpfile) {
152         errors = do_wtmp(&rec);
153     } else {
154         errors = do_acct(&rec);
155 #ifdef DB 
156     if (session.db_acct && rec.acct_type==ACCT_TYPE_STOP )
157         db_acct(&rec);
158 #endif
159         }
160
161     if (errors) {
162         status = TAC_PLUS_ACCT_STATUS_ERROR;
163     } else {
164         status = TAC_PLUS_ACCT_STATUS_SUCCESS;
165     }
166     send_acct_reply(status, rec.msg, rec.admin_msg);
167
168     free(identity.username);
169     free(identity.NAS_name);
170     free(identity.NAS_port);
171     free(identity.NAC_address);
172
173     for (i = 0; i < (int)acct_pak->arg_cnt; i++) {
174         free(cmd_argp[i]);
175     }    
176     free(cmd_argp);
177     
178     if (rec.msg)
179         free(rec.msg);
180     if (rec.admin_msg)
181         free(rec.admin_msg);
182 }