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