Ejemplo n.º 1
0
static void l2tp_toggle_debug(void)
{
#ifdef USL_DMALLOC
    dmalloc_log_unfreed();
    dmalloc_log_stats();
    dmalloc_log_heap_map();
#endif

    l2tp_opt_debug = !l2tp_opt_debug;
}
Ejemplo n.º 2
0
/* under Linux a sighandler must reenable itself */
void sig_handler(int sig) {

    logmsg(LOG_INFO, "%s: signal %i received", STR_PROGNAME, sig);
    signal(sig, sig_handler);

    output_stats();
    reset_stats();

#ifdef DMALLOC
    logmsg(LOG_DEBUG, "%s: dumping dmalloc statistics", STR_PROGNAME);
    dmalloc_log_stats();
    dmalloc_log_unfreed();
#endif
}
Ejemplo n.º 3
0
int main(int argc, char** argv) {
    int            c;
    char*          p;
    uid_t          uid, gid, client_gid, root_gid;
    struct passwd* pw;
    struct group*  gr;
    struct stat    st;
    int            localsocket = 1;


    /*
     * compilerwarnung: "client_gid may be used uninitialized"
     * sowas will man ja nun wirklich nicht ...
     */
    uid = gid = client_gid = root_gid = 0;

    while ((c = getopt(argc, argv, "bc:d:hfg:k:m:n:s:t:u:vx")) > 0) {
        switch (c) {
        case 'b': /* break contentheader */
            logmsg(LOG_INFO, "option -b is ignored for compatibily reasons, you may remove it safely");
            break;
        case 'c': /* clientgroup */
            opt_clientgroup = optarg;
            if ((gr = getgrnam(opt_clientgroup)) == NULL) {
                logmsg(LOG_ERR, "unknown clientgroup: getgrnam(%s) failed", opt_group);
                exit(EX_DATAERR);
            }
            client_gid = gr->gr_gid;
            break;
        case 'd': /* Loglevel */
            opt_loglevel = (int) strtoul(optarg, &p, 10);
            if (p != NULL && *p != '\0') {
                printf("debug-level is not valid integer: %s\n", optarg);
                exit(EX_DATAERR);
            }
            p = NULL;
            if (opt_loglevel < 0 || opt_loglevel > 7) {
                printf("loglevel out of range 0..7: %i\n", opt_loglevel);
                exit(EX_DATAERR);
            }
            break;
        case 'f': /* signer from header, not from envelope */
            opt_signerfromheader = 1;
            break;
        case 'g': /* group */
            opt_group = optarg;
            if ((gr = getgrnam(opt_group)) == NULL) {
                printf("unknown group: getgrnam(%s) failed", opt_group);
                exit(EX_DATAERR);
            }
            break;
        case 'k': /* keepdir */
            opt_keepdir = optarg;
            if (stat(opt_keepdir, &st) < 0) {
                printf("directory to keep data: %s: %s", opt_keepdir, strerror(errno));
                exit(EX_DATAERR);
            }
            if (!S_ISDIR(st.st_mode)) {
                printf("directory to keep data: %s is not a directory", opt_keepdir);
                exit(EX_DATAERR);
            }
            /* Zugriffsrechte werden spaeter geprueft, wenn zur richtigen uid gewechselt wurde */
            break;
        case '?': /* help */
        case 'h':
            usage();
            exit(EX_OK);
        case 'm': /* Signingtable cdbfilename */
            opt_signingtable = optarg;
            break;
        case 'n': /* Modetable cdbfilename */
            opt_modetable = optarg;
            break;
        case 's': /* Miltersocket */
            opt_miltersocket = optarg;
            break;
        case 't': /* Timeout */
            opt_timeout = (int) strtoul(optarg, &p, 10);
            if (p != NULL && *p != '\0') {
                printf("timeout is not valid integer: %s\n", optarg);
                exit(EX_DATAERR);
            }
            p = NULL;
            if (opt_timeout < 0 ) {
                printf("negative milter connection timeout: %i\n", opt_timeout);
                exit(EX_DATAERR);
            }
            break;
        case 'u': /* user */
            opt_user = optarg;
            /* get passwd/group entries for opt_user and opt_group */
            if ((pw = getpwnam(opt_user)) == NULL) {
                logmsg(LOG_ERR, "unknown user: getpwnam(%s) failed", opt_user);
                exit(EX_DATAERR);
            }
            break;
        case 'v': /* Version */
            version();
            exit(EX_OK);
        case 'x': /* add X-Header */
            opt_addxheader = (int) !opt_addxheader;
            break;
        default:
            usage();
            exit(EX_USAGE);
        }
    }

    /* open syslog an say helo */
    openlog(STR_PROGNAME, LOG_PID, LOG_MAIL);
    logmsg(LOG_NOTICE, "starting %s %s listening on %s, loglevel %i",
               STR_PROGNAME, STR_PROGVERSION, opt_miltersocket, opt_loglevel);

    /* force a new processgroup */
    if ((setsid() == -1))
        logmsg(LOG_DEBUG, "ignoring that setsid() failed");

    if (opt_timeout > 0 && smfi_settimeout(opt_timeout) != MI_SUCCESS) {
        logmsg(LOG_ERR, "could not set milter timeout");
        exit(EX_SOFTWARE);
    }
    logmsg(LOG_INFO, "miltertimeout set to %i", opt_timeout);

    if (smfi_setconn(opt_miltersocket) != MI_SUCCESS) {
        logmsg(LOG_ERR, "could not set milter socket");
        exit(EX_SOFTWARE);
    }

    if (smfi_register(callbacks) != MI_SUCCESS) {
        logmsg(LOG_ERR, "could not register milter");
        exit(EX_SOFTWARE);
    }

    /*
     * User- und Gruppennamen stehen nun fest. Testen, ob es diese gibt
     * und uid / gid ermitteln
     */
    if ((pw = getpwnam(opt_user)) == NULL) {
        logmsg(LOG_ERR, "unknown user: getpwnam(%s) failed", opt_user);
        exit(EX_DATAERR);
    }
    uid = pw->pw_uid;
    if ((gr = getgrnam(opt_group)) == NULL) {
        logmsg(LOG_ERR, "unknown group: getgrnam(%s) failed", opt_group);
        exit(EX_SOFTWARE);
    }
    gid = gr->gr_gid;

    /* wenn nicht als Parameter angegeben, gehört ein Unix-Socket erstmal der gleichen Gruppe */
    if (opt_clientgroup == NULL)
        client_gid = gid;

    /* wenn inet in optarg gefunden wird *und* das auch noch direkt am Anfang
     * dann ist's kein lokaler socket */
    if (((p = strstr(opt_miltersocket, "inet")) != NULL) && opt_miltersocket == p)
        localsocket = 0;

    if (localsocket == 1) {
        /* den Socket oeffnen */
        if (smfi_opensocket(REMOVE_EXISTING_SOCKETS) != MI_SUCCESS) {
            logmsg(LOG_ERR, "could not open milter socket %s", opt_miltersocket);
            exit(EX_SOFTWARE);
        }
        /* testen, ob's den Socket nun gibt */
        p = opt_miltersocket + strlen("local:");
        if (stat(p, &st) < 0) {
            p = opt_miltersocket + strlen("unix:");
            if (stat(p, &st) < 0) {
                logmsg(LOG_ERR, "miltersocket does not exist: %m", strerror(errno));
                exit(EX_DATAERR);
            }
        }

        /* gid der Gruppe root */
        if ((gr = getgrnam("root")) == NULL) {
            logmsg(LOG_ERR, "unknown rootgroup: getgrnam(root) failed");
            exit(EX_SOFTWARE);
        }
        root_gid = gr->gr_gid;

        /* clientgroup muss != root und != opt_group sein */
        if ((client_gid == gid) || (client_gid == root_gid)) {
            logmsg(LOG_ERR, "clientgroup %s must be neither %s nor %s", opt_clientgroup, "root", opt_group);
            exit(EX_DATAERR);
        }

        /* nun die Rechte setzen */
        if (chown(p, uid, client_gid) != 0) {
            logmsg(LOG_ERR, "chown(%s, %i, %i) failed: %m", p, uid, client_gid, strerror(errno));
            exit(EX_SOFTWARE);
        }
        if (chmod(p, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) != 0) {
            logmsg(LOG_ERR, "chmod(%s, 0660) failed: %m", p, strerror(errno));
            exit(EX_SOFTWARE);
        }

        logmsg(LOG_INFO, "changed socket %s to owner/group: %i/%i, mode: 0660", opt_miltersocket, uid, client_gid);
    }

    /* gid/uid setzen */
    if (setgid(gid) != 0) {
        logmsg(LOG_ERR, "setgid(%i) failed: %s", gr->gr_gid, strerror(errno));
        exit(EX_SOFTWARE);
    }
    if (setuid(uid) != 0) {
        logmsg(LOG_ERR, "setuid(%i) failed: %s", pw->pw_uid, strerror(errno));
        exit(EX_SOFTWARE);
    } 

    /* aktuelle uid/gid pruefen und loggen */
    uid = getuid();
    gid = getgid();
    if (uid == 0 || gid == 0) {
        logmsg(LOG_ERR, "too much priveleges, %s will not start under root", STR_PROGNAME);
        exit(EX_DATAERR);
    }
    logmsg(LOG_INFO, "running as uid: %i, gid: %i", (int) uid, (int) gid);

    if (opt_keepdir != NULL) {
        if (S_IRWXO & st.st_mode) {
            logmsg(LOG_ERR, "directory to keep data: %s: permissions too open: remove any access for other", opt_keepdir);
            exit(EX_DATAERR);
        }
        if (access(opt_keepdir, R_OK) < 0 && errno == EACCES) {
            logmsg(LOG_ERR, "directory to keep data: %s: permissions too strong: no read access", opt_keepdir);
            exit(EX_DATAERR);
        }
        if (access(opt_keepdir, W_OK) < 0 && errno == EACCES) {
            logmsg(LOG_ERR, "directory to keep data: %s: permissions too strong: no write access", opt_keepdir);
            exit(EX_DATAERR);
        }
        if (access(opt_keepdir, X_OK) < 0 && errno == EACCES) {
            logmsg(LOG_ERR, "directory to keep data: %s: permissions too strong: no execute access", opt_keepdir);
            exit(EX_DATAERR);
        }
        logmsg(LOG_INFO, "directory to keep data: %s", opt_keepdir);
    }

    dict_open(opt_signingtable, &dict_signingtable);
    if (opt_modetable)
        dict_open(opt_modetable, &dict_modetable);

    /* initialize OpenSSL */
    SSL_library_init();
    OpenSSL_add_all_algorithms();

    /* get meaningful error messages */
    SSL_load_error_strings();
    ERR_load_crypto_strings();

    /* Statistik initialisieren */
    init_stats();

    /* Signal-Handler fuer SIGALRM */
    signal(SIGALRM, sig_handler);

    /* Run milter */
    if ((c = smfi_main()) != MI_SUCCESS)
        logmsg(LOG_ERR, "Milter startup failed");
    else
        logmsg(LOG_NOTICE, "stopping %s %s listening on %s", STR_PROGNAME, STR_PROGVERSION, opt_miltersocket);

    dict_close(&dict_signingtable);
    if (opt_modetable)
        dict_close(&dict_modetable);

    /* cleanup OpenSSL */
    ERR_free_strings();
    EVP_cleanup();

    output_stats();

#ifdef DMALLOC
    dmalloc_log_stats();
    dmalloc_log_unfreed();
    dmalloc_shutdown();
#endif
    exit(c);
}
Ejemplo n.º 4
0
int main (int argc, char *argv[]) 
{
   int sts;
   int i;
   int buflen;
   int access;
   char buff [BUFFER_SIZE];
   sip_ticket_t ticket;

   extern char *optarg;         /* Defined in libc getopt and unistd.h */
   int ch1;
   
   char configfile[64]="siproxd";       /* basename of configfile */
   int  config_search=1;                /* search the config file */
   int  cmdline_debuglevel=0;
   char *pidfilename=NULL;
   struct sigaction act;

   log_set_stderr(1);

/*
 * 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(SIGUSR2, &act, NULL)) {
      ERROR("Failed to install SIGUSR2 handler");
   }


/*
 * prepare default configuration
 */
   make_default_config();

   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'},
      {"pid-file", required_argument, NULL,'p'},
      {0,0,0,0}
   };

    while ((ch1 = getopt_long(argc, argv, "hc:d:p:",
                  long_options, &option_index)) != -1) {
#else   /* ! HAVE_GETOPT_LONG */
    while ((ch1 = getopt(argc, argv, "hc:d:p:")) != -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);
         i=sizeof(configfile)-1;
         strncpy(configfile,optarg,i-1);
         configfile[i]='\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;

      case 'p':
         pidfilename = optarg;
         break;

      default:
         DEBUGC(DBCLASS_CONFIG,"no command line options");
         break; 
      }
   }
}

/*
 * Init stuff
 */
   INFO(PACKAGE"-"VERSION"-"BUILDSTR" "UNAME" starting up");

   /* 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;
   }

/*
 * open a the pwfile instance, so we still have access after
 * we possibly have chroot()ed to somewhere.
 */
   if (configuration.proxy_auth_pwfile) {
      siproxd_passwordfile = fopen(configuration.proxy_auth_pwfile, "r");
   } else {
      siproxd_passwordfile = NULL;
   }

   /* set debug level as desired */
   log_set_pattern(configuration.debuglevel);
   log_set_listen_port(configuration.debugport);

   /* 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_stderr(0);
      INFO("daemonized, pid=%i", getpid());
   }

   /* write PID file of main thread */
   if (pidfilename == NULL) pidfilename = configuration.pid_file;
   if (pidfilename) {
      FILE *pidfile;
      DEBUGC(DBCLASS_CONFIG,"creating PID file [%s]", pidfilename);
      sts=unlink(configuration.pid_file);
      if ((sts==0) ||(errno == ENOENT)) {
         if ((pidfile=fopen(pidfilename, "w"))) {
            fprintf(pidfile,"%i\n",(int)getpid());
            fclose(pidfile);
         } else {
            WARN("couldn't create new PID file: %s", strerror(errno));
         }
      } else {
         WARN("couldn't delete old PID file: %s", strerror(errno));
      }
   }

   /* 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();
   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();

/*
 * silence the log - if so required...
 */
   log_set_silence(configuration.silence_log);

   INFO(PACKAGE"-"VERSION"-"BUILDSTR" "UNAME" started");

/*****************************
 * Main loop
 *****************************/
   while (!exit_program) {

      DEBUGC(DBCLASS_BABBLE,"going into sipsock_wait\n");
      while (sipsock_wait()<=0) {
         /* got no input, here by timeout. do aging */
         register_agemap();

         /* TCP log: check for a connection */
         log_tcp_connect();

         /* dump memory stats if requested to do so */
         if (dmalloc_dump) {
            dmalloc_dump=0;
#ifdef DMALLOC
            INFO("SIGUSR2 - DMALLOC statistics is dumped");
            dmalloc_log_stats();
            dmalloc_log_unfreed();
#else
            INFO("SIGUSR2 - DMALLOC support is not compiled in");
#endif
         }

         if (exit_program) goto exit_prg;
      }

      /*
       * got input, process
       */
      DEBUGC(DBCLASS_BABBLE,"back from sipsock_wait");
      ticket.direction=0;

      buflen=sipsock_read(&buff, sizeof(buff)-1, &ticket.from,
                           &ticket.protocol);
      buff[buflen]='\0';

      /*
       * evaluate the access lists (IP based filter)
       */
      access=accesslist_check(ticket.from);
      if (access == 0) {
         DEBUGC(DBCLASS_ACCESS,"access for this packet was denied");
         continue; /* there are no resources to free */
      }

      /*
       * integrity checks
       */
      sts=security_check_raw(buff, buflen);
      if (sts != STS_SUCCESS) {
         DEBUGC(DBCLASS_SIP,"security check (raw) failed");
         continue; /* there are no resources to free */
      }

      /*
       * init sip_msg
       */
      sts=osip_message_init(&ticket.sipmsg);
      ticket.sipmsg->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=sip_message_parse(ticket.sipmsg, buff, buflen);
      if (sts != 0) {
         ERROR("sip_message_parse() failed... this is not good");
         DUMP_BUFFER(-1, buff, buflen);
         goto end_loop; /* skip and free resources */
      }

      /*
       * integrity checks - parsed buffer
       */
      sts=security_check_sip(&ticket);
      if (sts != STS_SUCCESS) {
         ERROR("security_check_sip() failed... this is not good");
         DUMP_BUFFER(-1, buff, buflen);
         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(ticket.sipmsg, 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(&ticket, 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(&ticket) == STS_TRUE) {
         /* make sure we don't end up in endless loop when detecting
          * an loop in an "loop detected" message - brrr */
         if (MSG_IS_RESPONSE(ticket.sipmsg) && 
             MSG_TEST_CODE(ticket.sipmsg, 482)) {
            DEBUGC(DBCLASS_SIP,"loop in loop-response detected, ignoring");
         } else {
            DEBUGC(DBCLASS_SIP,"via loop detected, ignoring request");
            sip_gen_response(&ticket, 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(ticket.sipmsg))? "REQ" : "RES",
             (MSG_IS_REQUEST(ticket.sipmsg) ?
                ((ticket.sipmsg->sip_method)?
                   ticket.sipmsg->sip_method : "NULL") :
                ((ticket.sipmsg->reason_phrase) ? 
                   ticket.sipmsg->reason_phrase : "NULL")));

      /*********************************
       * The message did pass all the
       * tests above and is now ready
       * to be proxied.
       * Before we do so, we apply some
       * additional preprocessing
       *********************************/
      /* Dial shortcuts */
      if (configuration.pi_shortdial) {
         sts = plugin_shortdial(&ticket);
         if (sts == STS_SIP_SENT) goto end_loop;
      }


      /*********************************
       * finally proxy the message.
       * This includes the masquerading
       * of the local UA and starting/
       * stopping the RTP proxy for this
       * call
       *********************************/

      /*
       * if a 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(ticket.sipmsg) && 
          MSG_IS_REQUEST(ticket.sipmsg)) {
         if (access & ACCESSCTL_REG) {
            osip_uri_t *url;
            struct in_addr addr1, addr2, addr3;
            int dest_port;

            url = osip_message_get_uri(ticket.sipmsg);
            dest_port= (url->port)?atoi(url->port):SIP_PORT;

            if ( (get_ip_by_host(url->host, &addr1) == STS_SUCCESS) &&
                 (get_interface_ip(IF_INBOUND,&addr2) == STS_SUCCESS) &&
                 (get_interface_ip(IF_OUTBOUND,&addr3) == STS_SUCCESS)) {

               if ((configuration.sip_listen_port == dest_port) &&
                   ((memcmp(&addr1, &addr2, sizeof(addr1)) == 0) ||
                    (memcmp(&addr1, &addr3, sizeof(addr1)) == 0))) {
                  /* I'm the registrar, send response myself */
                  sts = register_client(&ticket, 0);
                  sts = register_response(&ticket, sts);
               } else {
                  /* I'm just the outbound proxy */
                  DEBUGC(DBCLASS_SIP,"proxying REGISTER request to:%s",
                         url->host);
                  sts = register_client(&ticket, 1);
                  if (sts == STS_SUCCESS) {
                     sts = proxy_request(&ticket);
                  }
               }
            } else {
               sip_gen_response(&ticket, 408 /*request timeout*/);
            }
         } else {
            WARN("non-authorized registration attempt from %s",
                 utils_inet_ntoa(ticket.from.sin_addr));
         }

      /*
       * check if outbound interface is UP.
       * If not, send back error to UA and
       * skip any proxying attempt
       */
      } else if (get_interface_ip(IF_OUTBOUND,NULL) !=
                 STS_SUCCESS) {
         DEBUGC(DBCLASS_SIP, "got a %s to proxy, but outbound interface "
                "is down", (MSG_IS_REQUEST(ticket.sipmsg))? "REQ" : "RES");

         if (MSG_IS_REQUEST(ticket.sipmsg))
            sip_gen_response(&ticket, 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(ticket.sipmsg)) {
         if (access & ACCESSCTL_SIP) {
            sts = proxy_request(&ticket);
         } else {
            INFO("non-authorized request received from %s",
                 utils_inet_ntoa(ticket.from.sin_addr));
         }

      /*
       * MSG is a response, remove current via and
       * send to the next VIA in chain
       */
      } else if (MSG_IS_RESPONSE(ticket.sipmsg)) {
         if (access & ACCESSCTL_SIP) {
            sts = proxy_response(&ticket);
         } else {
            INFO("non-authorized response received from %s",
                 utils_inet_ntoa(ticket.from.sin_addr));
         }
         
      /*
       * unsupported message
       */
      } else {
         ERROR("received unsupported SIP type %s %s",
               (MSG_IS_REQUEST(ticket.sipmsg))? "REQ" : "RES",
               ticket.sipmsg->sip_method);
      }

      /*********************************
       * Done with proxying. Message
       * has been sent to its destination.
       *********************************/
/*
 * free the SIP message buffers
 */
      end_loop:
      osip_message_free(ticket.sipmsg);

   } /* while TRUE */
   exit_prg:

   /* save current known SIP registrations */
   register_save();
   INFO("properly terminating siproxd");

   /* remove PID file */
   if (pidfilename) {
      DEBUGC(DBCLASS_CONFIG,"deleting PID file [%s]", pidfilename);
      sts=unlink(pidfilename);
      if (sts != 0) {
         WARN("couldn't delete old PID file: %s", strerror(errno));
      }
   }

   /* END */
   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==SIGUSR2) dmalloc_dump=1;
   return;
}