⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 siproxd.c

📁 siproxd is a proxy/masquerading for the SIP protocal.
💻 C
字号:
/* -*- Mode: C; c-basic-offset: 3 -*-    Copyright (C) 2002  Thomas Ries <tries@gmx.net>    This file is part of Siproxd.        Siproxd 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.        Siproxd 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 Siproxd; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "config.h"#include <stdio.h>#include <errno.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#include <netinet/in.h>#include <arpa/inet.h>#ifdef	HAVE_GETOPT_H#include <getopt.h>#endif#include <osipparser2/osip_parser.h>#include "siproxd.h"#include "log.h"static char const ident[]="$Id: " __FILE__ ": " PACKAGE "-" VERSION "-"			  BUILDSTR " $";/* configuration storage */struct siproxd_config configuration;/* socket used for sending SIP datagrams */int sip_socket=0;/* -h help option text */static const char str_helpmsg[] =PACKAGE "-" VERSION "-" BUILDSTR " (c) 2002-2004 Thomas Ries\n""\nUsage: siproxd [options]\n\n""options:\n""       --help              (-h) help\n""       --debug <pattern>   (-d) set debug-pattern\n""       --config <cfgfile>  (-c) use the specified config file\n""";/* * module local data */static  int dmalloc_dump=0;static  int exit_program=0;/* * local prototypes */static void sighandler(int sig);int main (int argc, char *argv[]) {   int sts;   int i;   int access;   struct sockaddr_in from;   char buff [BUFFER_SIZE];   osip_message_t *my_msg=NULL;   extern char *optarg;   int ch1;      char configfile[64]="siproxd";	/* basename of configfile */   int  config_search=1;		/* search the config file */   int  cmdline_debuglevel=0;   struct sigaction act;/* * setup signal handlers */   act.sa_handler=sighandler;   sigemptyset(&act.sa_mask);   act.sa_flags=SA_RESTART;   if (sigaction(SIGTERM, &act, NULL)) {      ERROR("Failed to install SIGTERM handler");   }   if (sigaction(SIGINT, &act, NULL)) {      ERROR("Failed to install SIGINT handler");   }   if (sigaction(SIGUSR1, &act, NULL)) {      ERROR("Failed to install SIGUSR1 handler");   }/* * prepare default configuration */   memset (&configuration, 0, sizeof(configuration));   configuration.sip_listen_port=SIP_PORT;   log_set_pattern(configuration.debuglevel);      /* * parse command line */{#ifdef	HAVE_GETOPT_LONG   int option_index = 0;   static struct option long_options[] = {      {"help", no_argument, NULL, 'h'},      {"config", required_argument, NULL, 'c'},      {"debug", required_argument, NULL, 'd'},      {0,0,0,0}   };    while ((ch1 = getopt_long(argc, argv, "hc:d:n",                  long_options, &option_index)) != -1) {#else	/* ! HAVE_GETOPT_LONG */    while ((ch1 = getopt(argc, argv, "hc:d:n:")) != -1) {#endif      switch (ch1) {      case 'h':	/* help */         DEBUGC(DBCLASS_CONFIG,"option: help");         fprintf(stderr,str_helpmsg);         exit(0);	 break;      case 'c':	/* load config file */         DEBUGC(DBCLASS_CONFIG,"option: config file=%s",optarg);         strncpy(configfile,optarg,sizeof(configfile)-1);	 configfile[sizeof(configfile)]='\0';	 config_search=0;	 break;       case 'd':	/* set debug level */         DEBUGC(DBCLASS_CONFIG,"option: set debug level: %s",optarg);	 cmdline_debuglevel=atoi(optarg);         log_set_pattern(cmdline_debuglevel);	 break;      default:         DEBUGC(DBCLASS_CONFIG,"no command line options");	 break;       }   }}/* * Init stuff */   /* read the config file */   if (read_config(configfile, config_search) == STS_FAILURE) exit(1);   /* if a debug level > 0 has been given on the commandline use its      value and not what is in the config file */   if (cmdline_debuglevel != 0) {      configuration.debuglevel=cmdline_debuglevel;   }   /* set debug level as desired */   log_set_pattern(configuration.debuglevel);   /* change user and group IDs */   secure_enviroment();   /* daemonize if requested to */   if (configuration.daemonize) {      DEBUGC(DBCLASS_CONFIG,"daemonizing");      if (fork()!=0) exit(0);      setsid();      if (fork()!=0) exit(0);      log_set_tosyslog(1);      INFO("daemonized, pid=%i", getpid());   }   /* initialize the RTP proxy */   sts=rtpproxy_init();   if (sts != STS_SUCCESS) {      ERROR("unable to initialize RTP proxy - aborting");       exit(1);   }   /* init the oSIP parser */   parser_init();   /* listen for incoming messages */   sts=sipsock_listen(&sip_socket);   if (sts == STS_FAILURE) {      /* failure to allocate SIP socket... */      ERROR("unable to bind to SIP listening socket - aborting");       exit(1);   }   /* initialize the registration facility */   register_init();   INFO(PACKAGE"-"VERSION"-"BUILDSTR" started");/* * silence the log - if so required... */   log_set_silence(configuration.silence_log);/* * Main loop */   while (!exit_program) {      DEBUGC(DBCLASS_BABBLE,"going into sip_wait\n");      while (sipsock_wait(sip_socket)<=0) {         /* got no input, here by timeout. do aging */         register_agemap();         /* dump memory stats if requested to do so */         if (dmalloc_dump) {            dmalloc_dump=0;#ifdef DMALLOC            INFO("SIGUSR1 - DMALLOC statistics is dumped");            dmalloc_log_stats();            dmalloc_log_unfreed();#else            INFO("SIGUSR1 - DMALLOC support is not compiled in");#endif         }         if (exit_program) goto exit_prg;      }      /* got input, process */      DEBUGC(DBCLASS_BABBLE,"back from sip_wait");      i=sipsock_read(sip_socket, &buff, sizeof(buff)-1, &from);      buff[i]='\0';      /* evaluate the access lists (IP based filter)*/      access=accesslist_check(from);      if (access == 0) continue; /* there are no resources to free */      /* integrity checks */      sts=security_check_raw(buff, i);      if (sts != STS_SUCCESS) continue; /* there are no resources to free */      /* init sip_msg */      sts=osip_message_init(&my_msg);      my_msg->message=NULL;      if (sts != 0) {         ERROR("osip_message_init() failed... this is not good");	 continue; /* skip, there are no resources to free */      }      /*       * RFC 3261, Section 16.3 step 1       * Proxy Behavior - Request Validation - Reasonable Syntax       * (parse the received message)       */      sts=osip_message_parse(my_msg, buff);      if (sts != 0) {         ERROR("osip_message_parse() failed... this is not good");         DUMP_BUFFER(-1, buff, i);         goto end_loop; /* skip and free resources */      }      /* integrity checks - parsed buffer*/      sts=security_check_sip(my_msg);      if (sts != STS_SUCCESS) {         ERROR("security_check_sip() failed... this is not good");         DUMP_BUFFER(-1, buff, i);         goto end_loop; /* skip and free resources */      }      /*       * RFC 3261, Section 16.3 step 2       * Proxy Behavior - Request Validation - URI scheme       * (check request URI and refuse with 416 if not understood)       */      /* NOT IMPLEMENTED */      /*       * RFC 3261, Section 16.3 step 3       * Proxy Behavior - Request Validation - Max-Forwards check       * (check Max-Forwards header and refuse with 483 if too many hops)       */      {      osip_header_t *max_forwards;      int forwards_count = DEFAULT_MAXFWD;      osip_message_get_max_forwards(my_msg, 0, &max_forwards);      if (max_forwards && max_forwards->hvalue) {         forwards_count = atoi(max_forwards->hvalue);      }      DEBUGC(DBCLASS_PROXY,"checking Max-Forwards (=%i)",forwards_count);      if (forwards_count <= 0) {         DEBUGC(DBCLASS_SIP, "Forward count reached 0 -> 483 response");         sip_gen_response(my_msg, 483 /*Too many hops*/);         goto end_loop; /* skip and free resources */      }      }      /*       * RFC 3261, Section 16.3 step 4       * Proxy Behavior - Request Validation - Loop Detection check       * (check for loop and return 482 if a loop is detected)       */      if (check_vialoop(my_msg) == STS_TRUE) {         DEBUGC(DBCLASS_SIP,"via loop detected, ignoring request");         sip_gen_response(my_msg, 482 /*Loop detected*/);         goto end_loop; /* skip and free resources */      }      /*       * RFC 3261, Section 16.3 step 5       * Proxy Behavior - Request Validation - Proxy-Require check       * (check Proxy-Require header and return 420 if unsupported option)       */      /* NOT IMPLEMENTED */      /*       * RFC 3261, Section 16.5       * Proxy Behavior - Determining Request Targets       */      /* NOT IMPLEMENTED */      DEBUGC(DBCLASS_SIP,"received SIP type %s:%s",	     (MSG_IS_REQUEST(my_msg))? "REQ" : "RES",             (MSG_IS_REQUEST(my_msg) ?                ((my_msg->sip_method)? my_msg->sip_method : "NULL") :                ((my_msg->reason_phrase) ? my_msg->reason_phrase : "NULL")));                    /*       * if an REQ REGISTER, check if it is directed to myself,       * or am I just the outbound proxy but no registrar.       * - If I'm the registrar, register & generate answer       * - If I'm just the outbound proxy, register, rewrite & forward       */      if (MSG_IS_REGISTER(my_msg) && MSG_IS_REQUEST(my_msg)) {         if (access & ACCESSCTL_REG) {            osip_uri_t *url;            struct in_addr addr1, addr2, addr3;            url = osip_message_get_uri(my_msg);            sts = get_ip_by_host(url->host, &addr1);            get_ip_by_ifname(configuration.inbound_if,&addr2);            get_ip_by_ifname(configuration.outbound_if,&addr3);            if ((sts == STS_SUCCESS) &&                ((memcmp(&addr1, &addr2, sizeof(addr1)) == 0) ||                 (memcmp(&addr1, &addr3, sizeof(addr1)) == 0))) {               /* I'm the registrar, send response myself */               sts = register_client(my_msg, 0);               sts = register_response(my_msg, sts);            } else {               /* I'm just the outbound proxy */               DEBUGC(DBCLASS_SIP,"proxying REGISTER request to:%s",url->host);               sts = register_client(my_msg, 1);               sts = proxy_request(my_msg, &from);            }	 } else {            WARN("non-authorized registration attempt from %s",	         utils_inet_ntoa(from.sin_addr));	 }      /*       * check if outbound interface is UP.       * If not, send back error to UA and       * skip any proxying attempt       */      } else if (get_ip_by_ifname(configuration.outbound_if,NULL) !=                 STS_SUCCESS) {         DEBUGC(DBCLASS_SIP, "got a %s to proxy, but outbound interface "                "is down", (MSG_IS_REQUEST(my_msg))? "REQ" : "RES");         if (MSG_IS_REQUEST(my_msg))            sip_gen_response(my_msg, 408 /*request timeout*/);            /*       * MSG is a request, add current via entry,       * do a lookup in the URLMAP table and       * send to the final destination       */      } else if (MSG_IS_REQUEST(my_msg)) {         if (access & ACCESSCTL_SIP) {            sts = proxy_request(my_msg, &from);	 } else {            INFO("non-authorized request received from %s",	         utils_inet_ntoa(from.sin_addr));	 }      /*       * MSG is a response, remove current via and       * send to the next VIA in chain       */      } else if (MSG_IS_RESPONSE(my_msg)) {         if (access & ACCESSCTL_SIP) {            sts = proxy_response(my_msg, &from);	 } else {            INFO("non-authorized response received from %s",	         utils_inet_ntoa(from.sin_addr));	 }	       /*       * unsupported message       */      } else {         ERROR("received unsupported SIP type %s %s",	       (MSG_IS_REQUEST(my_msg))? "REQ" : "RES",	       my_msg->sip_method);      }/* * free the SIP message buffers */      end_loop:      osip_message_free(my_msg);   } /* while TRUE */   exit_prg:   register_shut();   INFO("properly terminating siproxd");   return 0;} /* main *//* * Signal handler * * this one is called asynchronously whevener a registered * signal is applied. Just set a flag and don't do any funny * things here. */static void sighandler(int sig) {   if (sig==SIGTERM) exit_program=1;   if (sig==SIGINT)  exit_program=1;   if (sig==SIGUSR1) dmalloc_dump=1;   return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -