📄 sipp.cpp
字号:
/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author : Richard GAYRAUD - 04 Nov 2003 * Marc LAMBERTON * Olivier JACQUES * Herve PELLAN * David MANSUTTI * Francois-Xavier Kowalski * From Hewlett Packard Company. * F. Tarek Rogers * Peter Higginson * Vincent Luba * Shriram Natarajan * Guillaume Teissier from FTR&D * Clement Chen */#define GLOBALS_FULL_DEFINITION#include "sipp.hpp"#ifdef _USE_OPENSSLSSL_CTX *sip_trp_ssl_ctx = NULL; /* For SSL cserver context */SSL_CTX *sip_trp_ssl_ctx_client = NULL; /* For SSL cserver context */SSL_CTX *twinSipp_sip_trp_ssl_ctx_client = NULL; /* For SSL cserver context */enum ssl_init_status { SSL_INIT_NORMAL, /* 0 Normal completion */ SSL_INIT_ERROR /* 1 Unspecified error */};#define CALL_BACK_USER_DATA "ksgr"int passwd_call_back_routine(char *buf , int size , int flag, void *passwd){ strncpy(buf, (char *)(passwd), size); buf[size - 1] = '\0'; return(strlen(buf));}#endif/***************** System Portability Features *****************/unsigned int getmilliseconds(){ struct timeval LS_system_time; unsigned long long int VI_milli; static unsigned long long int VI_milli_base = 0; gettimeofday(&LS_system_time, NULL); VI_milli = ((unsigned long long) LS_system_time.tv_sec) * 1000LL + (LS_system_time.tv_usec / 1000LL); if (!VI_milli_base) VI_milli_base = VI_milli - 1; VI_milli = VI_milli - VI_milli_base; return (unsigned int) VI_milli;}#ifdef _USE_OPENSSL/****** SSL error handling *************/void sip_tls_error_handling(SSL *ssl, int size) { int err; err=SSL_get_error(ssl, size); switch(err) { case SSL_ERROR_NONE: break; case SSL_ERROR_WANT_WRITE: WARNING("SSL_read returned SSL_ERROR_WANT_WRITE"); break; case SSL_ERROR_WANT_READ: WARNING("SSL_read returned SSL_ERROR_WANT_READ"); break; case SSL_ERROR_WANT_X509_LOOKUP: WARNING("SSL_read returned SSL_ERROR_WANT_X509_LOOKUP"); break; case SSL_ERROR_SYSCALL: if(size<0) { /* not EOF */ switch(errno) { case EINTR: WARNING("SSL_read interrupted by a signal"); break; case EAGAIN: WARNING("SSL_read returned EAGAIN"); break; default: WARNING("SSL_read (ERROR_SYSCALL)"); } } else { /* EOF */ WARNING("SSL socket closed on SSL_read"); } break; }}/****** Certificate Verification Callback FACILITY *************/int sip_tls_verify_callback(int ok , X509_STORE_CTX *store){ char data[512]; if (!ok) { X509 *cert = X509_STORE_CTX_get_current_cert(store); int depth = X509_STORE_CTX_get_error_depth(store); int err = X509_STORE_CTX_get_error(store); X509_NAME_oneline(X509_get_issuer_name(cert), data,512); WARNING_P1("TLS verification error for issuer: '%s'", data); X509_NAME_oneline(X509_get_subject_name(cert), data,512); WARNING_P1("TLS verification error for subject: '%s'", data); } return ok;}/*********** Load the CRL's into SSL_CTX **********************/int sip_tls_load_crls( SSL_CTX *ctx , char *crlfile){ X509_STORE *store; X509_LOOKUP *lookup; /* Get the X509_STORE from SSL context */ if (!(store = SSL_CTX_get_cert_store(ctx))) { return (-1); } /* Add lookup file to X509_STORE */ if (!(lookup = X509_STORE_add_lookup(store,X509_LOOKUP_file()))) { return (-1); } /* Add the CRLS to the lookpup object */ if (X509_load_crl_file(lookup,crlfile,X509_FILETYPE_PEM) != 1) { return (-1); } /* Set the flags of the store so that CRLS's are consulted */#if OPENSSL_VERSION_NUMBER >= 0x00907000L X509_STORE_set_flags( store,X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);#else#warning This version of OpenSSL (<0.9.7) cannot handle CRL files in capath ERROR("This version of OpenSSL (<0.9.7) cannot handle CRL files in capath");#endif return (1);}/************* Prepare the SSL context ************************/static ssl_init_status FI_init_ssl_context (void){ sip_trp_ssl_ctx = SSL_CTX_new( SSLv23_method() ); if ( sip_trp_ssl_ctx == NULL ) { ERROR("FI_init_ssl_context: SSL_CTX_new with SSLv23_method failed"); return SSL_INIT_ERROR; } sip_trp_ssl_ctx_client = SSL_CTX_new( TLSv1_method() ); if ( sip_trp_ssl_ctx_client == NULL) { ERROR("FI_init_ssl_context: SSL_CTX_new with TLSv1_method failed"); return SSL_INIT_ERROR; } /* Load the trusted CA's */ SSL_CTX_load_verify_locations(sip_trp_ssl_ctx, tls_cert_name, NULL); SSL_CTX_load_verify_locations(sip_trp_ssl_ctx_client, tls_cert_name, NULL); /* CRL load from application specified only if specified on the command line */ if (strlen(tls_crl_name) != 0) { if(sip_tls_load_crls(sip_trp_ssl_ctx,tls_crl_name) == -1) { ERROR_P1("FI_init_ssl_context: Unable to load CRL file (%s)", tls_crl_name); return SSL_INIT_ERROR; } if(sip_tls_load_crls(sip_trp_ssl_ctx_client,tls_crl_name) == -1) { ERROR_P1("FI_init_ssl_context: Unable to load CRL (client) file (%s)", tls_crl_name); return SSL_INIT_ERROR; } /* The following call forces to process the certificates with the */ /* initialised SSL_CTX */ SSL_CTX_set_verify(sip_trp_ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, sip_tls_verify_callback); SSL_CTX_set_verify(sip_trp_ssl_ctx_client, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, sip_tls_verify_callback); } /* Selection Cipher suits - load the application specified ciphers */ SSL_CTX_set_default_passwd_cb_userdata(sip_trp_ssl_ctx, (void *)CALL_BACK_USER_DATA ); SSL_CTX_set_default_passwd_cb_userdata(sip_trp_ssl_ctx_client, (void *)CALL_BACK_USER_DATA ); SSL_CTX_set_default_passwd_cb( sip_trp_ssl_ctx, passwd_call_back_routine ); SSL_CTX_set_default_passwd_cb( sip_trp_ssl_ctx_client, passwd_call_back_routine ); if ( SSL_CTX_use_certificate_file(sip_trp_ssl_ctx, tls_cert_name, SSL_FILETYPE_PEM ) != 1 ) { ERROR("FI_init_ssl_context: SSL_CTX_use_certificate_file failed"); return SSL_INIT_ERROR; } if ( SSL_CTX_use_certificate_file(sip_trp_ssl_ctx_client, tls_cert_name, SSL_FILETYPE_PEM ) != 1 ) { ERROR("FI_init_ssl_context: SSL_CTX_use_certificate_file (client) failed"); return SSL_INIT_ERROR; } if ( SSL_CTX_use_PrivateKey_file(sip_trp_ssl_ctx, tls_key_name, SSL_FILETYPE_PEM ) != 1 ) { ERROR("FI_init_ssl_context: SSL_CTX_use_PrivateKey_file failed"); return SSL_INIT_ERROR; } if ( SSL_CTX_use_PrivateKey_file(sip_trp_ssl_ctx_client, tls_key_name, SSL_FILETYPE_PEM ) != 1 ) { ERROR("FI_init_ssl_context: SSL_CTX_use_PrivateKey_file (client) failed"); return SSL_INIT_ERROR; } return SSL_INIT_NORMAL;}int send_nowait_tls(SSL *ssl, const void *msg, int len, int flags){ int initial_fd_flags; int rc; int fd; int fd_flags; if ( (fd = SSL_get_fd(ssl)) == -1 ) { return (-1); } fd_flags = fcntl(fd, F_GETFL , NULL); initial_fd_flags = fd_flags; fd_flags |= O_NONBLOCK; fcntl(fd, F_SETFL , fd_flags); rc = SSL_write(ssl,msg,len); if ( rc <= 0 ) { return(rc); } fcntl(fd, F_SETFL , initial_fd_flags); return rc;}#endif int send_nowait(int s, const void *msg, int len, int flags){#ifdef MSG_DONTWAIT return send(s, msg, len, flags | MSG_DONTWAIT);#else int fd_flags = fcntl(s, F_GETFL , NULL); int initial_fd_flags; int rc; initial_fd_flags = fd_flags; // fd_flags &= ~O_ACCMODE; // Remove the access mode from the value fd_flags |= O_NONBLOCK; fcntl(s, F_SETFL , fd_flags); rc = send(s, msg, len, flags); fcntl(s, F_SETFL , initial_fd_flags); return rc;#endif }char * get_inet_address(struct sockaddr_storage * addr){ static char * ip_addr = NULL; if (!ip_addr) { ip_addr = (char *)malloc(1024*sizeof(char)); } if (getnameinfo(_RCAST(struct sockaddr *, addr), SOCK_ADDR_SIZE(addr), ip_addr, 1024, NULL, 0, NI_NUMERICHOST) != 0) { strcpy(ip_addr, "addr not supported"); } return ip_addr;}void get_host_and_port(char * addr, char * host, int * port){ /* Separate the port number (if any) from the host name. * Thing is, the separator is a colon (':'). The colon may also exist * in the host portion if the host is specified as an IPv6 address (see * RFC 2732). If that's the case, then we need to skip past the IPv6 * address, which should be contained within square brackets ('[',']'). */ char *p; p = strchr( addr, '[' ); /* Look for '['. */ if( p != NULL ) { /* If found, look for ']'. */ p = strchr( p, ']' ); } if( p == NULL ) { /* If '['..']' not found, */ p = addr; /* scan the whole string. */ } else { /* If '['..']' found, */ char *p1; /* extract the remote_host */ char *p2; p1 = strchr( addr, '[' ); p2 = strchr( addr, ']' ); *p2 = '\0'; strcpy(host, p1 + 1); *p2 = ']'; } /* Starting at <p>, which is either the start of the host substring * or the end of the IPv6 address, find the last colon character. */ p = strchr( p, ':' ); if( NULL != p ) { *p = '\0'; *port = atol(p + 1); } else { *port = 0; }}char * strcasestr2(char *s, char *find) { char c, sc; size_t len; if ((c = *find++) != 0) { c = tolower((unsigned char)c); len = strlen(find); do { do { if ((sc = *s++) == 0) return (NULL); } while ((char)tolower((unsigned char)sc) != c); } while (strncasecmp(s, find, len) != 0); s--; } return ((char *)s);}/******************** Recv Poll Processing *********************/int pollnfds;struct pollfd pollfiles[SIPP_MAXFDS];call * pollcalls[SIPP_MAXFDS];map<string, int> map_perip_fd;#ifdef _USE_OPENSSLSSL * ssl_list[SIPP_MAXFDS];#endifchar * pending_msg[SIPP_MAXFDS];/***************** Check of the message received ***************/bool sipMsgCheck (char *P_msg, int P_msgSize#ifdef __3PCC__ ,int P_pollSetIdx#endif ) { const char C_sipHeader[] = "SIP/2.0" ;#ifdef __3PCC__ if (pollfiles[P_pollSetIdx].fd == twinSippSocket) { return true ; } else {#endif // __3PCC__ if (strstr(P_msg, C_sipHeader) != NULL) { return true ; } return false ;#ifdef __3PCC__ }#endif // __3PCC__}void pollset_reset(){ pollnfds = 0; memset((void *)pending_msg,0,SIPP_MAXFDS*sizeof(char *)); memset((void *)pollfiles,0,SIPP_MAXFDS*sizeof(struct pollfd)); pollfiles[pollnfds].fd = main_socket; pollfiles[pollnfds].events = POLLIN | POLLERR; pollfiles[pollnfds].revents = 0; pollcalls[pollnfds] = NULL; pollnfds++; if(tcp_multiplex) { /* Adds the TCP multiplex in the file descriptor array */ pollfiles[pollnfds].fd = tcp_multiplex; pollfiles[pollnfds].events = POLLIN | POLLERR; pollfiles[pollnfds].revents = 0; pollcalls[pollnfds] = NULL; pollnfds++; } #ifdef __3PCC__ if(twinSippSocket) { /* Adds the twinSippSocket */ pollfiles[pollnfds].fd = twinSippSocket; pollfiles[pollnfds].events = POLLIN | POLLERR; pollfiles[pollnfds].revents = 0; pollcalls[pollnfds] = NULL; pollnfds++; } if(localTwinSippSocket) { /* Adds the twinSippSocket */ pollfiles[pollnfds].fd = localTwinSippSocket; pollfiles[pollnfds].events = POLLIN | POLLERR; pollfiles[pollnfds].revents = 0; pollcalls[pollnfds] = NULL; pollnfds++; } #endif // Add additional server sockets for socket per IP address if (peripsocket && toolMode == MODE_SERVER) { for (map<string, int>::iterator i = map_perip_fd.begin(); i != map_perip_fd.end(); i++) { // main_socket is already in pollfiles if (i->second != main_socket) { pollset_add(0, i->second); } } }}int pollset_add(call * p_call, int sock){ pollfiles[pollnfds].fd = sock; pollfiles[pollnfds].events = POLLIN | POLLERR; pollfiles[pollnfds].revents = 0; pollcalls[pollnfds] = p_call; pollnfds++; /* int L_i ; TRACE_MSG((s,"Adding socket : %d at idx = %d\n", sock, (pollnfds-1))); for (L_i = 0; L_i < pollnfds ; L_i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -