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