xref: /onnv-gate/usr/src/lib/libsip/common/sip_logging.c (revision 5842:e93f793783f6)
1*5842Sgm209912 /*
2*5842Sgm209912  * CDDL HEADER START
3*5842Sgm209912  *
4*5842Sgm209912  * The contents of this file are subject to the terms of the
5*5842Sgm209912  * Common Development and Distribution License (the "License").
6*5842Sgm209912  * You may not use this file except in compliance with the License.
7*5842Sgm209912  *
8*5842Sgm209912  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5842Sgm209912  * or http://www.opensolaris.org/os/licensing.
10*5842Sgm209912  * See the License for the specific language governing permissions
11*5842Sgm209912  * and limitations under the License.
12*5842Sgm209912  *
13*5842Sgm209912  * When distributing Covered Code, include this CDDL HEADER in each
14*5842Sgm209912  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5842Sgm209912  * If applicable, add the following below this CDDL HEADER, with the
16*5842Sgm209912  * fields enclosed by brackets "[]" replaced with your own identifying
17*5842Sgm209912  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5842Sgm209912  *
19*5842Sgm209912  * CDDL HEADER END
20*5842Sgm209912  */
21*5842Sgm209912 
22*5842Sgm209912 /*
23*5842Sgm209912  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*5842Sgm209912  * Use is subject to license terms.
25*5842Sgm209912  */
26*5842Sgm209912 
27*5842Sgm209912 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*5842Sgm209912 
29*5842Sgm209912 #include <stdio.h>
30*5842Sgm209912 #include <string.h>
31*5842Sgm209912 #include <strings.h>
32*5842Sgm209912 #include <stdlib.h>
33*5842Sgm209912 #include <assert.h>
34*5842Sgm209912 #include <ctype.h>
35*5842Sgm209912 #include <errno.h>
36*5842Sgm209912 #include <sip.h>
37*5842Sgm209912 
38*5842Sgm209912 #include "sip_msg.h"
39*5842Sgm209912 #include "sip_miscdefs.h"
40*5842Sgm209912 #include "sip_xaction.h"
41*5842Sgm209912 #include "sip_dialog.h"
42*5842Sgm209912 
43*5842Sgm209912 #define	TIME_BUF_SIZE	50
44*5842Sgm209912 
45*5842Sgm209912 /*
46*5842Sgm209912  * Contains API's which enable/disable transaction or dialog logging,
47*5842Sgm209912  * API's which records/measures SIP Traffic.
48*5842Sgm209912  */
49*5842Sgm209912 /*
50*5842Sgm209912  * Needed for measuring SIP traffic counters.
51*5842Sgm209912  */
52*5842Sgm209912 sip_traffic_counters_t	sip_counters;
53*5842Sgm209912 
54*5842Sgm209912 /*
55*5842Sgm209912  * Needed for dialog/transaction logging.
56*5842Sgm209912  */
57*5842Sgm209912 sip_logfile_t trans_log;
58*5842Sgm209912 sip_logfile_t dialog_log;
59*5842Sgm209912 
60*5842Sgm209912 /*
61*5842Sgm209912  * This function increments the appropriate inbound/outbound counters for
62*5842Sgm209912  * SIP requests/responses.
63*5842Sgm209912  */
64*5842Sgm209912 void
sip_measure_traffic(boolean_t is_request,sip_method_t method,int resp_code,boolean_t outbound,int msg_size)65*5842Sgm209912 sip_measure_traffic(boolean_t is_request, sip_method_t method, int resp_code,
66*5842Sgm209912     boolean_t outbound, int msg_size)
67*5842Sgm209912 {
68*5842Sgm209912 #ifdef	__solaris__
69*5842Sgm209912 	assert(mutex_held(&sip_counters.sip_counter_mutex));
70*5842Sgm209912 #endif
71*5842Sgm209912 	if (outbound)
72*5842Sgm209912 		sip_counters.sip_total_bytes_sent += msg_size;
73*5842Sgm209912 	else
74*5842Sgm209912 		sip_counters.sip_total_bytes_rcvd += msg_size;
75*5842Sgm209912 
76*5842Sgm209912 	if (is_request) {
77*5842Sgm209912 		if (outbound)
78*5842Sgm209912 			++sip_counters.sip_total_req_sent;
79*5842Sgm209912 		else
80*5842Sgm209912 			++sip_counters.sip_total_req_rcvd;
81*5842Sgm209912 		switch (method) {
82*5842Sgm209912 			case INVITE:
83*5842Sgm209912 				if (outbound)
84*5842Sgm209912 					++sip_counters.sip_invite_req_sent;
85*5842Sgm209912 				else
86*5842Sgm209912 					++sip_counters.sip_invite_req_rcvd;
87*5842Sgm209912 				break;
88*5842Sgm209912 			case ACK:
89*5842Sgm209912 				if (outbound)
90*5842Sgm209912 					++sip_counters.sip_ack_req_sent;
91*5842Sgm209912 				else
92*5842Sgm209912 					++sip_counters.sip_ack_req_rcvd;
93*5842Sgm209912 				break;
94*5842Sgm209912 			case OPTIONS:
95*5842Sgm209912 				if (outbound)
96*5842Sgm209912 					++sip_counters.sip_options_req_sent;
97*5842Sgm209912 				else
98*5842Sgm209912 					++sip_counters.sip_options_req_rcvd;
99*5842Sgm209912 				break;
100*5842Sgm209912 			case BYE:
101*5842Sgm209912 				if (outbound)
102*5842Sgm209912 					++sip_counters.sip_bye_req_sent;
103*5842Sgm209912 				else
104*5842Sgm209912 					++sip_counters.sip_bye_req_rcvd;
105*5842Sgm209912 				break;
106*5842Sgm209912 			case CANCEL:
107*5842Sgm209912 				if (outbound)
108*5842Sgm209912 					++sip_counters.sip_cancel_req_sent;
109*5842Sgm209912 				else
110*5842Sgm209912 					++sip_counters.sip_cancel_req_rcvd;
111*5842Sgm209912 				break;
112*5842Sgm209912 			case REGISTER:
113*5842Sgm209912 				if (outbound)
114*5842Sgm209912 					++sip_counters.sip_register_req_sent;
115*5842Sgm209912 				else
116*5842Sgm209912 					++sip_counters.sip_register_req_rcvd;
117*5842Sgm209912 				break;
118*5842Sgm209912 			case REFER:
119*5842Sgm209912 				if (outbound)
120*5842Sgm209912 					++sip_counters.sip_refer_req_sent;
121*5842Sgm209912 				else
122*5842Sgm209912 					++sip_counters.sip_refer_req_rcvd;
123*5842Sgm209912 				break;
124*5842Sgm209912 			case INFO:
125*5842Sgm209912 				if (outbound)
126*5842Sgm209912 					++sip_counters.sip_info_req_sent;
127*5842Sgm209912 				else
128*5842Sgm209912 					++sip_counters.sip_info_req_rcvd;
129*5842Sgm209912 				break;
130*5842Sgm209912 			case SUBSCRIBE:
131*5842Sgm209912 				if (outbound)
132*5842Sgm209912 					++sip_counters.sip_subscribe_req_sent;
133*5842Sgm209912 				else
134*5842Sgm209912 					++sip_counters.sip_subscribe_req_rcvd;
135*5842Sgm209912 				break;
136*5842Sgm209912 			case NOTIFY:
137*5842Sgm209912 				if (outbound)
138*5842Sgm209912 					++sip_counters.sip_notify_req_sent;
139*5842Sgm209912 				else
140*5842Sgm209912 					++sip_counters.sip_notify_req_rcvd;
141*5842Sgm209912 				break;
142*5842Sgm209912 			case PRACK:
143*5842Sgm209912 				if (outbound)
144*5842Sgm209912 					++sip_counters.sip_prack_req_sent;
145*5842Sgm209912 				else
146*5842Sgm209912 					++sip_counters.sip_prack_req_rcvd;
147*5842Sgm209912 				break;
148*5842Sgm209912 			default:
149*5842Sgm209912 				break;
150*5842Sgm209912 		}
151*5842Sgm209912 	} else {
152*5842Sgm209912 		if (outbound)
153*5842Sgm209912 			++sip_counters.sip_total_resp_sent;
154*5842Sgm209912 		else
155*5842Sgm209912 			++sip_counters.sip_total_resp_rcvd;
156*5842Sgm209912 		if (SIP_PROVISIONAL_RESP(resp_code)) {
157*5842Sgm209912 			if (outbound)
158*5842Sgm209912 				++sip_counters.sip_1xx_resp_sent;
159*5842Sgm209912 			else
160*5842Sgm209912 				++sip_counters.sip_1xx_resp_rcvd;
161*5842Sgm209912 		} else if (SIP_OK_RESP(resp_code)) {
162*5842Sgm209912 			if (outbound)
163*5842Sgm209912 				++sip_counters.sip_2xx_resp_sent;
164*5842Sgm209912 			else
165*5842Sgm209912 				++sip_counters.sip_2xx_resp_rcvd;
166*5842Sgm209912 		} else if (SIP_REDIRECT_RESP(resp_code)) {
167*5842Sgm209912 			if (outbound)
168*5842Sgm209912 				++sip_counters.sip_3xx_resp_sent;
169*5842Sgm209912 			else
170*5842Sgm209912 				++sip_counters.sip_3xx_resp_rcvd;
171*5842Sgm209912 		} else if (SIP_REQFAIL_RESP(resp_code)) {
172*5842Sgm209912 			if (outbound)
173*5842Sgm209912 				++sip_counters.sip_4xx_resp_sent;
174*5842Sgm209912 			else
175*5842Sgm209912 				++sip_counters.sip_4xx_resp_rcvd;
176*5842Sgm209912 		} else if (SIP_SRVFAIL_RESP(resp_code)) {
177*5842Sgm209912 			if (outbound)
178*5842Sgm209912 				++sip_counters.sip_5xx_resp_sent;
179*5842Sgm209912 			else
180*5842Sgm209912 				++sip_counters.sip_5xx_resp_rcvd;
181*5842Sgm209912 		} else if (SIP_GLOBFAIL_RESP(resp_code)) {
182*5842Sgm209912 			if (outbound)
183*5842Sgm209912 				++sip_counters.sip_6xx_resp_sent;
184*5842Sgm209912 			else
185*5842Sgm209912 				++sip_counters.sip_6xx_resp_rcvd;
186*5842Sgm209912 		}
187*5842Sgm209912 	}
188*5842Sgm209912 }
189*5842Sgm209912 
190*5842Sgm209912 /*
191*5842Sgm209912  * Enables Transaction logging. The flags argument controls the detail
192*5842Sgm209912  * of logging.
193*5842Sgm209912  */
194*5842Sgm209912 int
sip_enable_trans_logging(FILE * logfile,int flags)195*5842Sgm209912 sip_enable_trans_logging(FILE *logfile, int flags)
196*5842Sgm209912 {
197*5842Sgm209912 	if (logfile == NULL || flags != SIP_DETAIL_LOGGING)
198*5842Sgm209912 		return (EINVAL);
199*5842Sgm209912 
200*5842Sgm209912 	(void) pthread_mutex_lock(&trans_log.sip_logfile_mutex);
201*5842Sgm209912 	if (!trans_log.sip_logging_enabled) {
202*5842Sgm209912 		trans_log.sip_logfile = logfile;
203*5842Sgm209912 		trans_log.sip_logging_enabled = B_TRUE;
204*5842Sgm209912 	}
205*5842Sgm209912 	(void) pthread_mutex_unlock(&trans_log.sip_logfile_mutex);
206*5842Sgm209912 	return (0);
207*5842Sgm209912 }
208*5842Sgm209912 
209*5842Sgm209912 
210*5842Sgm209912 /*
211*5842Sgm209912  * Enables dialog logging. The flags argument controls the detail
212*5842Sgm209912  * of logging.
213*5842Sgm209912  */
214*5842Sgm209912 int
sip_enable_dialog_logging(FILE * logfile,int flags)215*5842Sgm209912 sip_enable_dialog_logging(FILE *logfile, int flags)
216*5842Sgm209912 {
217*5842Sgm209912 	if (logfile == NULL || flags != SIP_DETAIL_LOGGING)
218*5842Sgm209912 		return (EINVAL);
219*5842Sgm209912 
220*5842Sgm209912 	(void) pthread_mutex_lock(&dialog_log.sip_logfile_mutex);
221*5842Sgm209912 	if (!dialog_log.sip_logging_enabled) {
222*5842Sgm209912 		dialog_log.sip_logfile = logfile;
223*5842Sgm209912 		dialog_log.sip_logging_enabled = B_TRUE;
224*5842Sgm209912 	}
225*5842Sgm209912 	(void) pthread_mutex_unlock(&dialog_log.sip_logfile_mutex);
226*5842Sgm209912 	return (0);
227*5842Sgm209912 }
228*5842Sgm209912 
229*5842Sgm209912 void
sip_disable_trans_logging()230*5842Sgm209912 sip_disable_trans_logging()
231*5842Sgm209912 {
232*5842Sgm209912 	(void) pthread_mutex_lock(&trans_log.sip_logfile_mutex);
233*5842Sgm209912 	if (trans_log.sip_logging_enabled)
234*5842Sgm209912 		trans_log.sip_logging_enabled = B_FALSE;
235*5842Sgm209912 	(void) pthread_mutex_unlock(&trans_log.sip_logfile_mutex);
236*5842Sgm209912 }
237*5842Sgm209912 
238*5842Sgm209912 void
sip_disable_dialog_logging()239*5842Sgm209912 sip_disable_dialog_logging()
240*5842Sgm209912 {
241*5842Sgm209912 	(void) pthread_mutex_lock(&dialog_log.sip_logfile_mutex);
242*5842Sgm209912 	if (dialog_log.sip_logging_enabled)
243*5842Sgm209912 		dialog_log.sip_logging_enabled = B_FALSE;
244*5842Sgm209912 	(void) pthread_mutex_unlock(&dialog_log.sip_logfile_mutex);
245*5842Sgm209912 }
246*5842Sgm209912 
247*5842Sgm209912 static void
sip_print_digest(uint16_t * digest,int len,FILE * fp)248*5842Sgm209912 sip_print_digest(uint16_t *digest, int len, FILE *fp)
249*5842Sgm209912 {
250*5842Sgm209912 	int	cnt;
251*5842Sgm209912 
252*5842Sgm209912 	for (cnt = 0; cnt < len; cnt++)
253*5842Sgm209912 		(void) fprintf(fp, "%u ", digest[cnt]);
254*5842Sgm209912 	(void) fprintf(fp, "\n\n");
255*5842Sgm209912 }
256*5842Sgm209912 
257*5842Sgm209912 /*
258*5842Sgm209912  * Logs all the messages exchanged within a transaction to the transaction
259*5842Sgm209912  * log file. Logged messages are then freed.
260*5842Sgm209912  */
261*5842Sgm209912 static void
sip_write_xaction_to_log(void * obj)262*5842Sgm209912 sip_write_xaction_to_log(void *obj)
263*5842Sgm209912 {
264*5842Sgm209912 	sip_xaction_t	*trans = (sip_xaction_t *)obj;
265*5842Sgm209912 	sip_log_t	*sip_log;
266*5842Sgm209912 	int		count;
267*5842Sgm209912 	sip_msg_chain_t	*msg_chain;
268*5842Sgm209912 	sip_msg_chain_t	*nmsg_chain;
269*5842Sgm209912 	char		timebuf[TIME_BUF_SIZE];
270*5842Sgm209912 	struct tm	tms;
271*5842Sgm209912 	FILE		*sip_trans_logfile = trans_log.sip_logfile;
272*5842Sgm209912 
273*5842Sgm209912 	assert(trans != NULL && sip_trans_logfile != NULL);
274*5842Sgm209912 	(void) fprintf(sip_trans_logfile, "************* Begin Transaction"
275*5842Sgm209912 	    " *************\n");
276*5842Sgm209912 	(void) fprintf(sip_trans_logfile, "Branchid\t\t: %s\n",
277*5842Sgm209912 	    trans->sip_xaction_branch_id);
278*5842Sgm209912 	(void) fprintf(sip_trans_logfile, "Digest\t\t\t: ");
279*5842Sgm209912 	sip_print_digest(trans->sip_xaction_hash_digest, 8, sip_trans_logfile);
280*5842Sgm209912 	(void) fprintf(sip_trans_logfile, "-----------------------------\n");
281*5842Sgm209912 	for (count = 0; count <= SIP_SRV_NONINV_TERMINATED; count++) {
282*5842Sgm209912 		sip_log = &trans->sip_xaction_log[count];
283*5842Sgm209912 		if (sip_log->sip_msgcnt == 0)
284*5842Sgm209912 			continue;
285*5842Sgm209912 		(void) fprintf(sip_trans_logfile, "Transaction State\t: %s\n\n",
286*5842Sgm209912 		    sip_get_xaction_state(count));
287*5842Sgm209912 		msg_chain = sip_log->sip_msgs;
288*5842Sgm209912 		while (msg_chain != NULL) {
289*5842Sgm209912 			nmsg_chain = msg_chain->next;
290*5842Sgm209912 			(void) strftime(timebuf, sizeof (timebuf), NULL,
291*5842Sgm209912 			    localtime_r(&msg_chain->msg_timestamp, &tms));
292*5842Sgm209912 			(void) fprintf(sip_trans_logfile, "%s| Message -"
293*5842Sgm209912 			    " %d\n%s", timebuf, msg_chain->msg_seq, msg_chain->
294*5842Sgm209912 			    sip_msg);
295*5842Sgm209912 			free(msg_chain->sip_msg);
296*5842Sgm209912 			free(msg_chain);
297*5842Sgm209912 			--sip_log->sip_msgcnt;
298*5842Sgm209912 			msg_chain = nmsg_chain;
299*5842Sgm209912 		}
300*5842Sgm209912 		(void) fprintf(sip_trans_logfile,
301*5842Sgm209912 		    "-----------------------------\n");
302*5842Sgm209912 		(trans->sip_xaction_log[count]).sip_msgs = NULL;
303*5842Sgm209912 	}
304*5842Sgm209912 	(void) fprintf(sip_trans_logfile, "************* End Transaction "
305*5842Sgm209912 	    "*************\n");
306*5842Sgm209912 	(void) fflush(sip_trans_logfile);
307*5842Sgm209912 }
308*5842Sgm209912 
309*5842Sgm209912 /*
310*5842Sgm209912  * Logs all the messages exchanged within a dialog to the dialog
311*5842Sgm209912  * log file. Logged messages are then freed.
312*5842Sgm209912  */
313*5842Sgm209912 static void
sip_write_dlg_to_log(void * obj)314*5842Sgm209912 sip_write_dlg_to_log(void *obj)
315*5842Sgm209912 {
316*5842Sgm209912 	_sip_dialog_t	*dialog = (_sip_dialog_t *)obj;
317*5842Sgm209912 	sip_log_t	*sip_log;
318*5842Sgm209912 	int		count;
319*5842Sgm209912 	sip_msg_chain_t	*msg_chain;
320*5842Sgm209912 	sip_msg_chain_t	*nmsg_chain;
321*5842Sgm209912 	char		timebuf[TIME_BUF_SIZE];
322*5842Sgm209912 	struct tm	tms;
323*5842Sgm209912 	FILE		*sip_dialog_logfile = dialog_log.sip_logfile;
324*5842Sgm209912 
325*5842Sgm209912 	assert(dialog != NULL && sip_dialog_logfile != NULL);
326*5842Sgm209912 
327*5842Sgm209912 	(void) fprintf(sip_dialog_logfile, "************* Begin Dialog "
328*5842Sgm209912 	    "*************\n");
329*5842Sgm209912 	(void) fprintf(sip_dialog_logfile, "Digest\t\t\t: ");
330*5842Sgm209912 	sip_print_digest(dialog->sip_dlg_id, 8, sip_dialog_logfile);
331*5842Sgm209912 	(void) fprintf(sip_dialog_logfile, "-----------------------------\n");
332*5842Sgm209912 	for (count = 0; count <= SIP_DLG_DESTROYED; count++) {
333*5842Sgm209912 		sip_log = &dialog->sip_dlg_log[count];
334*5842Sgm209912 		if (sip_log->sip_msgcnt == 0)
335*5842Sgm209912 			continue;
336*5842Sgm209912 		(void) fprintf(sip_dialog_logfile, "Dialog State\t\t: %s\n\n",
337*5842Sgm209912 		    sip_get_dialog_state_str(count));
338*5842Sgm209912 		msg_chain = sip_log->sip_msgs;
339*5842Sgm209912 		while (msg_chain != NULL) {
340*5842Sgm209912 			nmsg_chain = msg_chain->next;
341*5842Sgm209912 			(void) strftime(timebuf, sizeof (timebuf), NULL,
342*5842Sgm209912 			    localtime_r(&msg_chain->msg_timestamp, &tms));
343*5842Sgm209912 			(void) fprintf(sip_dialog_logfile, "%s| Message -"
344*5842Sgm209912 			    " %d\n%s", timebuf, msg_chain->msg_seq, msg_chain->
345*5842Sgm209912 			    sip_msg);
346*5842Sgm209912 			free(msg_chain->sip_msg);
347*5842Sgm209912 			free(msg_chain);
348*5842Sgm209912 			--sip_log->sip_msgcnt;
349*5842Sgm209912 			msg_chain = nmsg_chain;
350*5842Sgm209912 		}
351*5842Sgm209912 		(void) fprintf(sip_dialog_logfile,
352*5842Sgm209912 		    "-----------------------------\n");
353*5842Sgm209912 		(dialog->sip_dlg_log[count]).sip_msgs = NULL;
354*5842Sgm209912 	}
355*5842Sgm209912 	(void) fprintf(sip_dialog_logfile, "************* End Dialog "
356*5842Sgm209912 	    "*************\n");
357*5842Sgm209912 	(void) fflush(sip_dialog_logfile);
358*5842Sgm209912 }
359*5842Sgm209912 
360*5842Sgm209912 /*
361*5842Sgm209912  * Calls the appropriate function to log transaction or dialog messages.
362*5842Sgm209912  * If this function is called because of assertion failure, then the file and
363*5842Sgm209912  * line where the assertion failed is logged to the log file.
364*5842Sgm209912  */
365*5842Sgm209912 void
sip_write_to_log(void * obj,int type,char * file,int line)366*5842Sgm209912 sip_write_to_log(void *obj, int type, char *file, int line)
367*5842Sgm209912 {
368*5842Sgm209912 	if (type & SIP_TRANSACTION_LOG) {
369*5842Sgm209912 		(void) pthread_mutex_lock(&trans_log.sip_logfile_mutex);
370*5842Sgm209912 		if (trans_log.sip_logging_enabled) {
371*5842Sgm209912 			if (type & SIP_ASSERT_ERROR) {
372*5842Sgm209912 				(void) fprintf(trans_log.sip_logfile,
373*5842Sgm209912 				    "Assertion Failure at %s:%d\n", file, line);
374*5842Sgm209912 			}
375*5842Sgm209912 			sip_write_xaction_to_log(obj);
376*5842Sgm209912 		}
377*5842Sgm209912 		(void) pthread_mutex_unlock(&trans_log.sip_logfile_mutex);
378*5842Sgm209912 	} else {
379*5842Sgm209912 		(void) pthread_mutex_lock(&dialog_log.sip_logfile_mutex);
380*5842Sgm209912 		if (dialog_log.sip_logging_enabled) {
381*5842Sgm209912 			if (type & SIP_ASSERT_ERROR) {
382*5842Sgm209912 				(void) fprintf(dialog_log.sip_logfile,
383*5842Sgm209912 				    "Assertion Failure at %s:%d\n", file, line);
384*5842Sgm209912 			}
385*5842Sgm209912 			sip_write_dlg_to_log(obj);
386*5842Sgm209912 		}
387*5842Sgm209912 		(void) pthread_mutex_unlock(&dialog_log.sip_logfile_mutex);
388*5842Sgm209912 	}
389*5842Sgm209912 }
390*5842Sgm209912 
391*5842Sgm209912 /*
392*5842Sgm209912  * This function records the messages that are exchanged within a dialog or
393*5842Sgm209912  * transaction. If logging is enabled the recorded messages are then dumped
394*5842Sgm209912  * to the log file just before deleting the transaction or dialog.
395*5842Sgm209912  */
396*5842Sgm209912 void
sip_add_log(sip_log_t * sip_log,sip_msg_t sip_msg,int seq,int type)397*5842Sgm209912 sip_add_log(sip_log_t *sip_log, sip_msg_t sip_msg, int seq, int type)
398*5842Sgm209912 {
399*5842Sgm209912 	char			*msgstr;
400*5842Sgm209912 	sip_msg_chain_t		*new_msg;
401*5842Sgm209912 	sip_msg_chain_t		*msg_chain = sip_log->sip_msgs;
402*5842Sgm209912 
403*5842Sgm209912 	/*
404*5842Sgm209912 	 * No need to take any locks here. Caller of this function MUST
405*5842Sgm209912 	 * have already taken the transaction or dialog lock.
406*5842Sgm209912 	 */
407*5842Sgm209912 	if (((type == SIP_DIALOG_LOG) && !dialog_log.sip_logging_enabled) ||
408*5842Sgm209912 	    ((type == SIP_TRANSACTION_LOG) && !trans_log.sip_logging_enabled)) {
409*5842Sgm209912 		return;
410*5842Sgm209912 	}
411*5842Sgm209912 
412*5842Sgm209912 	new_msg = calloc(1, sizeof (sip_msg_chain_t));
413*5842Sgm209912 	if (new_msg == NULL)
414*5842Sgm209912 		return;
415*5842Sgm209912 
416*5842Sgm209912 	msgstr = sip_msg_to_str(sip_msg, NULL);
417*5842Sgm209912 	if (msgstr == NULL) {
418*5842Sgm209912 		free(new_msg);
419*5842Sgm209912 		return;
420*5842Sgm209912 	}
421*5842Sgm209912 
422*5842Sgm209912 	new_msg->sip_msg =  msgstr;
423*5842Sgm209912 	new_msg->msg_seq = seq;
424*5842Sgm209912 	new_msg->msg_timestamp = time(NULL);
425*5842Sgm209912 	new_msg->next = NULL;
426*5842Sgm209912 	if (sip_log->sip_msgcnt == 0) {
427*5842Sgm209912 		sip_log->sip_msgs = new_msg;
428*5842Sgm209912 	} else {
429*5842Sgm209912 		while (msg_chain->next != NULL)
430*5842Sgm209912 			msg_chain = msg_chain->next;
431*5842Sgm209912 		msg_chain->next = new_msg;
432*5842Sgm209912 	}
433*5842Sgm209912 	sip_log->sip_msgcnt++;
434*5842Sgm209912 }
435*5842Sgm209912 
436*5842Sgm209912 /*
437*5842Sgm209912  * Given a counter group and counter name within the group, returns the value
438*5842Sgm209912  * associated with the counter in 'cntval'.
439*5842Sgm209912  */
440*5842Sgm209912 int
sip_get_counter_value(int group,int counter,void * cntval,size_t cntlen)441*5842Sgm209912 sip_get_counter_value(int group, int counter, void *cntval, size_t cntlen)
442*5842Sgm209912 {
443*5842Sgm209912 	if (group != SIP_TRAFFIC_COUNTERS || cntval == NULL)
444*5842Sgm209912 		return (EINVAL);
445*5842Sgm209912 	if ((counter == SIP_COUNTER_START_TIME || counter ==
446*5842Sgm209912 	    SIP_COUNTER_STOP_TIME) && (cntlen != sizeof (time_t))) {
447*5842Sgm209912 		return (EINVAL);
448*5842Sgm209912 	} else if (cntlen != sizeof (uint64_t)) {
449*5842Sgm209912 		return (EINVAL);
450*5842Sgm209912 	}
451*5842Sgm209912 
452*5842Sgm209912 	(void) pthread_mutex_lock(&sip_counters.sip_counter_mutex);
453*5842Sgm209912 	switch (counter) {
454*5842Sgm209912 		case SIP_TOTAL_BYTES_RCVD:
455*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_total_bytes_rcvd;
456*5842Sgm209912 			break;
457*5842Sgm209912 		case SIP_TOTAL_BYTES_SENT:
458*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_total_bytes_sent;
459*5842Sgm209912 			break;
460*5842Sgm209912 		case SIP_TOTAL_REQ_RCVD:
461*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_total_req_rcvd;
462*5842Sgm209912 			break;
463*5842Sgm209912 		case SIP_TOTAL_REQ_SENT:
464*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_total_req_sent;
465*5842Sgm209912 			break;
466*5842Sgm209912 		case SIP_TOTAL_RESP_RCVD:
467*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_total_resp_rcvd;
468*5842Sgm209912 			break;
469*5842Sgm209912 		case SIP_TOTAL_RESP_SENT:
470*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_total_resp_sent;
471*5842Sgm209912 			break;
472*5842Sgm209912 		case SIP_ACK_REQ_RCVD:
473*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_ack_req_rcvd;
474*5842Sgm209912 			break;
475*5842Sgm209912 		case SIP_ACK_REQ_SENT:
476*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_ack_req_sent;
477*5842Sgm209912 			break;
478*5842Sgm209912 		case SIP_BYE_REQ_RCVD:
479*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_bye_req_rcvd;
480*5842Sgm209912 			break;
481*5842Sgm209912 		case SIP_BYE_REQ_SENT:
482*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_bye_req_sent;
483*5842Sgm209912 			break;
484*5842Sgm209912 		case SIP_CANCEL_REQ_RCVD:
485*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_cancel_req_rcvd;
486*5842Sgm209912 			break;
487*5842Sgm209912 		case SIP_CANCEL_REQ_SENT:
488*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_cancel_req_sent;
489*5842Sgm209912 			break;
490*5842Sgm209912 		case SIP_INFO_REQ_RCVD:
491*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_info_req_rcvd;
492*5842Sgm209912 			break;
493*5842Sgm209912 		case SIP_INFO_REQ_SENT:
494*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_info_req_sent;
495*5842Sgm209912 			break;
496*5842Sgm209912 		case SIP_INVITE_REQ_RCVD:
497*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_invite_req_rcvd;
498*5842Sgm209912 			break;
499*5842Sgm209912 		case SIP_INVITE_REQ_SENT:
500*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_invite_req_sent;
501*5842Sgm209912 			break;
502*5842Sgm209912 		case SIP_NOTIFY_REQ_RCVD:
503*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_notify_req_rcvd;
504*5842Sgm209912 			break;
505*5842Sgm209912 		case SIP_NOTIFY_REQ_SENT:
506*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_notify_req_sent;
507*5842Sgm209912 			break;
508*5842Sgm209912 		case SIP_OPTIONS_REQ_RCVD:
509*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_options_req_rcvd;
510*5842Sgm209912 			break;
511*5842Sgm209912 		case SIP_OPTIONS_REQ_SENT:
512*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_options_req_sent;
513*5842Sgm209912 			break;
514*5842Sgm209912 		case SIP_PRACK_REQ_RCVD:
515*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_prack_req_rcvd;
516*5842Sgm209912 			break;
517*5842Sgm209912 		case SIP_PRACK_REQ_SENT:
518*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_prack_req_sent;
519*5842Sgm209912 			break;
520*5842Sgm209912 		case SIP_REFER_REQ_RCVD:
521*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_refer_req_rcvd;
522*5842Sgm209912 			break;
523*5842Sgm209912 		case SIP_REFER_REQ_SENT:
524*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_refer_req_sent;
525*5842Sgm209912 			break;
526*5842Sgm209912 		case SIP_REGISTER_REQ_RCVD:
527*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.
528*5842Sgm209912 			    sip_register_req_rcvd;
529*5842Sgm209912 			break;
530*5842Sgm209912 		case SIP_REGISTER_REQ_SENT:
531*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.
532*5842Sgm209912 			    sip_register_req_sent;
533*5842Sgm209912 			break;
534*5842Sgm209912 		case SIP_SUBSCRIBE_REQ_RCVD:
535*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.
536*5842Sgm209912 			    sip_subscribe_req_rcvd;
537*5842Sgm209912 			break;
538*5842Sgm209912 		case SIP_SUBSCRIBE_REQ_SENT:
539*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.
540*5842Sgm209912 			    sip_subscribe_req_sent;
541*5842Sgm209912 			break;
542*5842Sgm209912 		case SIP_UPDATE_REQ_RCVD:
543*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_update_req_rcvd;
544*5842Sgm209912 			break;
545*5842Sgm209912 		case SIP_UPDATE_REQ_SENT:
546*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_update_req_sent;
547*5842Sgm209912 			break;
548*5842Sgm209912 		case SIP_1XX_RESP_RCVD:
549*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_1xx_resp_rcvd;
550*5842Sgm209912 			break;
551*5842Sgm209912 		case SIP_1XX_RESP_SENT:
552*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_1xx_resp_sent;
553*5842Sgm209912 			break;
554*5842Sgm209912 		case SIP_2XX_RESP_RCVD:
555*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_2xx_resp_rcvd;
556*5842Sgm209912 			break;
557*5842Sgm209912 		case SIP_2XX_RESP_SENT:
558*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_2xx_resp_sent;
559*5842Sgm209912 			break;
560*5842Sgm209912 		case SIP_3XX_RESP_RCVD:
561*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_3xx_resp_rcvd;
562*5842Sgm209912 			break;
563*5842Sgm209912 		case SIP_3XX_RESP_SENT:
564*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_3xx_resp_sent;
565*5842Sgm209912 			break;
566*5842Sgm209912 		case SIP_4XX_RESP_RCVD:
567*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_4xx_resp_rcvd;
568*5842Sgm209912 			break;
569*5842Sgm209912 		case SIP_4XX_RESP_SENT:
570*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_4xx_resp_sent;
571*5842Sgm209912 			break;
572*5842Sgm209912 		case SIP_5XX_RESP_RCVD:
573*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_5xx_resp_rcvd;
574*5842Sgm209912 			break;
575*5842Sgm209912 		case SIP_5XX_RESP_SENT:
576*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_5xx_resp_sent;
577*5842Sgm209912 			break;
578*5842Sgm209912 		case SIP_6XX_RESP_RCVD:
579*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_6xx_resp_rcvd;
580*5842Sgm209912 			break;
581*5842Sgm209912 		case SIP_6xx_RESP_SENT:
582*5842Sgm209912 			*(uint64_t *)cntval = sip_counters.sip_6xx_resp_sent;
583*5842Sgm209912 			break;
584*5842Sgm209912 		case SIP_COUNTER_START_TIME:
585*5842Sgm209912 			*(time_t *)cntval = sip_counters.starttime;
586*5842Sgm209912 			break;
587*5842Sgm209912 		case SIP_COUNTER_STOP_TIME:
588*5842Sgm209912 			*(time_t *)cntval = sip_counters.stoptime;
589*5842Sgm209912 			break;
590*5842Sgm209912 		default:
591*5842Sgm209912 			(void) pthread_mutex_unlock(&sip_counters.
592*5842Sgm209912 			    sip_counter_mutex);
593*5842Sgm209912 			return (EINVAL);
594*5842Sgm209912 	}
595*5842Sgm209912 	(void) pthread_mutex_unlock(&sip_counters.sip_counter_mutex);
596*5842Sgm209912 	return (0);
597*5842Sgm209912 }
598*5842Sgm209912 
599*5842Sgm209912 /*
600*5842Sgm209912  * Enables the SIP performance/traffic counting. Also reset's the previous
601*5842Sgm209912  * counter values and starts counting afresh.
602*5842Sgm209912  */
603*5842Sgm209912 int
sip_enable_counters(int group)604*5842Sgm209912 sip_enable_counters(int group)
605*5842Sgm209912 {
606*5842Sgm209912 	if (group != SIP_TRAFFIC_COUNTERS)
607*5842Sgm209912 		return (EINVAL);
608*5842Sgm209912 	(void) pthread_mutex_lock(&sip_counters.sip_counter_mutex);
609*5842Sgm209912 	/* If it's not enabled, enable it and capture the start time */
610*5842Sgm209912 	if (!sip_counters.enabled) {
611*5842Sgm209912 		/* zero all the counters except for the mutex at the end */
612*5842Sgm209912 		(void) bzero(&sip_counters, sizeof (sip_traffic_counters_t) -
613*5842Sgm209912 		    sizeof (pthread_mutex_t));
614*5842Sgm209912 		sip_counters.enabled = B_TRUE;
615*5842Sgm209912 		sip_counters.starttime = time(NULL);
616*5842Sgm209912 		sip_counters.stoptime = 0;
617*5842Sgm209912 	}
618*5842Sgm209912 	(void) pthread_mutex_unlock(&sip_counters.sip_counter_mutex);
619*5842Sgm209912 	return (0);
620*5842Sgm209912 }
621*5842Sgm209912 
622*5842Sgm209912 /*
623*5842Sgm209912  * Disables the SIP performance/traffic counting. If already disabled it just
624*5842Sgm209912  * exits without doing anyting. It records the stop time.
625*5842Sgm209912  */
626*5842Sgm209912 int
sip_disable_counters(int group)627*5842Sgm209912 sip_disable_counters(int group)
628*5842Sgm209912 {
629*5842Sgm209912 	if (group != SIP_TRAFFIC_COUNTERS)
630*5842Sgm209912 		return (EINVAL);
631*5842Sgm209912 	(void) pthread_mutex_lock(&sip_counters.sip_counter_mutex);
632*5842Sgm209912 	if (sip_counters.enabled) {
633*5842Sgm209912 		sip_counters.enabled = B_FALSE;
634*5842Sgm209912 		sip_counters.stoptime = time(NULL);
635*5842Sgm209912 	}
636*5842Sgm209912 	(void) pthread_mutex_unlock(&sip_counters.sip_counter_mutex);
637*5842Sgm209912 	return (0);
638*5842Sgm209912 }
639