├── .gitignore ├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── Makefile.am ├── NEWS ├── README ├── RELNOTES ├── TODO ├── acinclude.m4 ├── autogen.sh ├── config.h.in ├── configure.ac ├── contrib ├── .gitignore ├── Makefile.am ├── asterisk_chan_sip_xar.patch └── siproxd.init ├── doc ├── .gitignore ├── FAQ ├── FLI4L_HOWTO.txt ├── KNOWN_BUGS ├── Makefile.am ├── RFC3261_compliance.txt ├── ReleaseProcedure.txt ├── build_FreeBSD.doc ├── devel.txt ├── sample_asterisk.txt ├── sample_cfg_budgetone.txt ├── sample_cfg_x-lite.txt ├── siproxd.conf.example ├── siproxd_guide.sgml └── siproxd_passwd.cfg ├── scripts ├── .gitignore ├── compile ├── config.guess ├── config.sub ├── depcomp ├── install-sh ├── ltmain.sh └── missing ├── siproxd.spec.in ├── src ├── .gitignore ├── Makefile.am ├── accessctl.c ├── auth.c ├── custom_fw_module.c ├── dejitter.c ├── dejitter.h ├── digcalc.h ├── fwapi.c ├── fwapi.h ├── log.c ├── log.h ├── plugin_blacklist.c ├── plugin_codecfilter.c ├── plugin_defaulttarget.c ├── plugin_demo.c ├── plugin_fix_DTAG.c ├── plugin_fix_bogus_via.c ├── plugin_fix_fbox_anoncall.c ├── plugin_logcall.c ├── plugin_prefix.c ├── plugin_regex.c ├── plugin_regex_body.c ├── plugin_shortdial.c ├── plugin_siptrunk.c ├── plugin_stats.c ├── plugin_stripheader.c ├── plugin_stun.c ├── plugins.c ├── plugins.h ├── proxy.c ├── readconf.c ├── redirect_cache.c ├── redirect_cache.h ├── register.c ├── resolve.c ├── route_processing.c ├── rtpproxy.c ├── rtpproxy.h ├── rtpproxy_relay.c ├── security.c ├── sip_layer.c ├── sip_utils.c ├── siproxd.c ├── siproxd.h ├── sock.c └── utils.c ├── stamp-h.in └── tools ├── extract_sip.pl └── sipp_testing ├── README ├── myuac.xml └── myuas.xml /.gitignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | Makefile.in 3 | configure 4 | config.log 5 | libltdl 6 | config.h 7 | config.h.in 8 | siproxd.spec 9 | config.status 10 | stamp-h1 11 | libtool 12 | autom4te.cache 13 | aclocal.m4 14 | m4 15 | siproxd-[0-9]*.[0-9]*.[0-9]*.tar.gz 16 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Thomas Ries (tries@gmx.net) 2 | GnuPG Public Key: 3 | pub 1024D/87BCDC94 2000-03-19 Thomas Ries (tries@gmx.net) 4 | Key fingerprint = 13D1 19F5 77D0 4CEC 8D3F A24E 09FC C18A 87BC DC94 5 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hb9xar/siproxd/0bb5dd4aac9f5578db664d82f67091bc83c3780d/ChangeLog -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2002-2008 Thomas Ries 3 | # 4 | # This file is part of Siproxd. 5 | # 6 | # Siproxd is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Siproxd is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Siproxd; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | 21 | 22 | OPT_LTDL_DIR = libltdl 23 | 24 | SUBDIRS = $(OPT_LTDL_DIR) src doc contrib 25 | #&&&INCLUDES = $(LTDLINCL) 26 | ACLOCAL_AMFLAGS = -I m4 27 | 28 | EXTRA_DIST = TODO RELNOTES siproxd.spec autogen.sh 29 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hb9xar/siproxd/0bb5dd4aac9f5578db664d82f67091bc83c3780d/NEWS -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 2 | 3 | Be warned, this (and all the other) documentation is far from 4 | complete. This is still considered an alpha release. 5 | 6 | 7 | OVERVIEW 8 | ======== 9 | Siproxd is a proxy/masquerading daemon for SIP (Session Initiation 10 | Protocol), which is used in IP telephony. 11 | It handles registrations of SIP clients on a private IP network 12 | and performs rewriting of the SIP message bodies to make SIP 13 | connections work via a masquerading firewall (NAT). 14 | It allows SIP software clients (like kphone, linphone) or SIP 15 | hardware clients (Voice over IP phones which are SIP-compatible, 16 | such as those from Cisco, Grandstream or Snom) to work behind 17 | an IP masquerading firewall or NAT router. 18 | 19 | SIP (Session Initiation Protocol, RFC3261) is the protocol of 20 | choice for most VoIP (Voice over IP) phones to initiate 21 | communication. By itself, SIP does not work via masquerading 22 | firewalls as the transfered data contains IP addresses and 23 | port numbers. There do exist other solutions to traverse NAT existing 24 | (like STUN, or SIP aware NAT routers), but such a solutions has its 25 | disadvantages or may not be applied to a given situation. 26 | Siproxd does not aim to be a replacement for these solutions, 27 | however in some situations siproxd may bring advantages. 28 | 29 | 30 | PREREQUISITES 31 | ============= 32 | - OS of either: 33 | * Linux (preferred kernel 2.2.x or 2.4.x) 34 | * FreeBSD 35 | * NetBSD 36 | * OpenBSD 37 | * SunOS 38 | * Mac OS X 39 | 40 | - libosip2 package (http://www.fsf.org/software/osip/) 41 | 42 | 43 | 44 | HOW TO GET STARTED 45 | ================== 46 | - make sure libosip2 is installed 47 | If your libposip2 libraries are installed in 48 | /usr/local/lib, be sure to include this library path to /etc/ld.so.conf 49 | 50 | - ./configure 51 | For Flifl: see doc/FLI4L_HOWTO.txt 52 | 53 | - make 54 | 55 | - make install 56 | 57 | - edit /usr/etc/siproxd.conf according to your situation 58 | At least configure 'if_inbound' and 'if_outbound'. The must represent 59 | the interface names (e.g. on Linux: ppp0, eth1) for the inbound 60 | and outbound interface. 61 | 62 | 63 | - edit /usr/etc/siproxd_passwd.cfg if you enable client authentication 64 | in siproxd.conf 65 | 66 | - start siproxd (siproxd does *not* require root privileges) 67 | $ siproxd 68 | 69 | 70 | 71 | PROBLEM REPORTING 72 | ================= 73 | If you encounter problems/crashes and ask for support, please include 74 | as much information as possible. Very helpful is a debug log that 75 | has been recorded at the time of the misbehavior. 76 | Also include the exact versions of the siproxd package and libosip2 77 | that you are using. You should also include your siproxd.conf. 78 | 79 | 80 | The easiest way to generate a debug log is: 81 | 1) make sure siproxd is not started as daemon. 82 | -> 'daemonize = 0' in the config file. 83 | 2) start siproxd: 84 | $ ./siproxd -d -1 2>debug.log 85 | 3) reproduce the error 86 | 4) include the file debug.log in your error report. 87 | 88 | Since Version 0.5.10 there also exists the possibility to obtain 89 | the debug log remote via TCP (useful if running siproxd on an embedded 90 | system). To enable this feature, edit the configuration file and 91 | set 'debug_port' to a free TCP port number (e.g. 5050). Then (after 92 | starting siproxd) you can connect from any remote client to this 93 | TCP port (e.g. using netcat) and all the debug output will be sent 94 | via network: 95 | 1) edit configuration file: 96 | -> 'daemonize = 1' have siproxd started as daemon 97 | -> 'silence_log' should be set to 1 98 | -> 'debug_level = -1' 99 | -> 'debug_port = 5050' (or any other TCP port you like) 100 | 2) have siproxd started the usual way 101 | 3) connect from a remote machine and write into a file: 102 | $ netcat > debug.log 103 | 4) reproduce the error 104 | 5) include the file debug.log in your error report. 105 | 106 | 107 | If siproxd crashes, a stack backtrace usually is helpful to me: 108 | 1) start siproxd in the debugger (daemonize set to 0): 109 | $ gdb ./src/siproxd 110 | (gdb) set args -c /path/to/siproxd.conf 111 | (gdb) run 112 | 2) reproduce the crash 113 | 3) use gdb to print the stack backtrace: 114 | (gdb) info thread 115 | ... 116 | (gdb) bt 117 | #0 0x400ec9ee in __select () 118 | #1 0xbffff6f8 in ?? () 119 | #2 0x804a5c2 in main (argc=3, argv=0xbffffc54) at siproxd.c:186 120 | #3 0x4005bcb3 in __libc_start_main (main=0x804a30c
, argc=3, 121 | argv=0xbffffc54, init=0x8049a08 <_init>, fini=0x804edac <_fini>, 122 | rtld_fini=0x4000a350 <_dl_fini>, stack_end=0xbffffc4c) 123 | at ../sysdeps/generic/libc-start.c:78 124 | (gdb) 125 | 4) copy-paste all the output and include it in your error report. 126 | 127 | 128 | 129 | SENDING A PATCH 130 | =============== 131 | If you send a patch, please make the diff using "diff -Naur" and 132 | include the version of siproxd you used to patch. This makes it a lot 133 | easier for me to merge it. 134 | 135 | 136 | WHAT SIPROXD DOES 137 | ================= 138 | Siproxd's purpose is to act as an SIP proxy for SIP softphones/hardphones 139 | located behind an masquerading router (NAT). It will rewrite SIP messages 140 | to allow a SIP phone to communicate to a counterpart that is located in 141 | the Internet. Check the scenarios drawn below. 142 | 143 | 144 | 145 | Scenario 1 146 | ---------- 147 | 148 | private IP address range : Internet 149 | 10.0.0.x : (public IP address range) 150 | : 151 | : foo.bar.org 152 | +-------------+ +--------------+ 153 | ! !.10 .1 ! masquerading ! publicIP 154 | ! IntHost !---------------! Firewall !------------>> 155 | ! ! ! ! 156 | +-------------+ +--------------+ 157 | eth0 : ppp0 158 | 159 | - The Firewall does IP masquerading (NAT) and is running siproxd 160 | 161 | - IntHost is running an SIP phone (like linphone, kphone) 162 | 163 | - The SIP address used by the SIP phone is sip:johndoe@foo.bar.org 164 | 165 | - The SIP phone is configured to register itself at siproxd 166 | running on the firewall host (10.0.0.1) as sip:johndoe@foo.bar.org 167 | 168 | - foo.bar.org is the domain name corresponding to the public IP address 169 | of the firewall (e.g. use some dynamic DNS service [1]) 170 | 171 | 172 | Scenario 2 173 | ---------- 174 | 175 | private IP address range : Internet 176 | 10.0.0.x : (public IP address range) 177 | : 178 | : foo.bar.org 179 | +-------------+ +--------------+ +--------------+ 180 | ! !.10 .1 ! masquerading ! publicIP ! external SIP ! 181 | ! IntHost !---------------! Firewall !------------>>! Registrar ! 182 | ! ! ! ! ! ! 183 | +-------------+ +--------------+ +--------------+ 184 | eth0 : ppp0 185 | 186 | - The Firewall does IP masquerading (NAT) and is running siproxd 187 | 188 | - IntHost is running an SIP phone (like linphone, kphone) 189 | 190 | - The SIP address used by the SIP phone is sip:johndoe@foo.bar.org 191 | 192 | - The SIP phone is configured to register itself at the external
193 | registrar as sip:johndoe@foo.bar.org 194 | 195 | - foo.bar.org is the domain name corresponding to the public IP address 196 | of the firewall (e.g. use some dynamic DNS service [1]) 197 | 198 | 199 | IPCHAINS: 200 | Firewall rules for incoming traffic: 201 | # ipchains -A input --proto udp --dport 5060 --log -j ACCEPT 202 | # ipchains -A input --proto udp --dport 7070:7080 -j ACCEPT 203 | 204 | IPTABLES: 205 | Firewall rules for incoming traffic: 206 | # iptables -A INPUT -i ppp0 -p udp -m udp --dport 5060 -j ACCEPT 207 | # iptables -A INPUT -i ppp0 -p udp -m udp --dport 7070:7080 -j ACCEPT 208 | 209 | The first line will allow incoming SIP traffic (UDP port 5060). The second 210 | line will allow incoming RTP traffic on the ports 7070-7080 (the default port 211 | range used by siproxd for incoming RTP traffic).

212 | 213 | 214 | REFERENCES 215 | ========== 216 | [1] dynamic DNS service http://www.dyndns.org 217 | 218 | 219 | 220 | LIMITATIONS 221 | =========== 222 | - currently, the SIP part only supports UDP 223 | - very likely it does not follow the SIP spec (RFC3261) in all details 224 | - check the TODO file for more things that we-cannot-do-but-would-like-to 225 | 226 | 227 | IMPORTANT NOTICE 228 | ================ 229 | The gethostbyname() function leaks memory in glibc 2.1.1 (-> RedHat 6.0). 230 | The quick fix is to delete the nisplus service from hosts entry in 231 | /etc/nsswitch.conf. 232 | In my tests, memory usage remained stable after I made the mentioned change. 233 | 234 | (source: http://www.squid-cache.org/Doc/FAQ/FAQ-14.html) 235 | 236 | 237 | CONTACTS 238 | ======== 239 | Please feel free to contact the author to: 240 | - provide feedback, report bugs, 241 | - request for additional features 242 | - report interoperability with various phones 243 | - ... 244 | and visit the website at http://siproxd.sourceforge.net/ 245 | 246 | A siproxd mailing list is available on sourceforge. 247 | 248 | IRC: Libera.Chat #siproxd 249 | 250 | 251 | GnuPG: pub 4096R/9D777F7D2AC27400 2017-07-11 252 | - Fingerprint = 6560 75BE 4D4D 6C4D 8005 D4B4 9D77 7F7D 2AC2 7400 253 | - PubKey via keys.openpgp.org 254 | 255 | 256 | CREDITS 257 | ======= 258 | 259 | Thanks to sourceforge.net for providing the distribution platform and 260 | infrastructure. 261 | 262 | Also credits to the maintainers of linphone from where I have taken some 263 | code parts for MD5 proxy authentication. 264 | 265 | -------------------------------------------------------------------------------- /RELNOTES: -------------------------------------------------------------------------------- 1 | Release Notes for siproxd-0.8.4 2 | =============================== 3 | 4 | 5 | 6 | Major changes since 0.8.3: 7 | - 8 | 9 | 10 | New plugins: 11 | - 12 | 13 | Upgrade Notes 0.8.3 to 0.8.4: 14 | - Merge the configuration file 15 | 16 | General Overview: 17 | - SIP (RFC3261) Proxy for SIP based softphones hidden behind a 18 | masquerading firewall 19 | - plugin system allows loading extensions to accomplish various tasks 20 | - Support for PRACK messages (RFC3262) 21 | - Support for UPDATE messages (RFC3311) 22 | - SIP UDP and TCP supported 23 | - Works with "dial-up" connections (dynamic IP addresses) 24 | - Multiple local users/hosts can be masqueraded simultaneously 25 | - Access control (IP based) for incoming traffic 26 | - Proxy Authentication for registration of local clients (User Agents) 27 | with individual passwords for each user 28 | - May be used as pure outbound proxy (registration of local UAs 29 | to a 3rd party registrar) 30 | - runs on various operating systems (see below) 31 | - Full duplex RTP data stream proxy for *incoming* and *outgoing* 32 | audio data - no firewall masquerading entries needed 33 | - Port range to be used for RTP traffic is configurable 34 | (-> easy to set up appropriate firewall rules for RTP traffic) 35 | - RTP proxy can handle multiple RTP streams (eg. audio + video) 36 | within a single SIP session. 37 | - Symmetric RTP support 38 | - Symmetric SIP signaling support 39 | - Supports running in a chroot jail and changing user-ID after startup 40 | - All configuration done via one simple ASCII configuration file 41 | - Logging to syslog in daemon mode 42 | - RPM package (Spec file) 43 | - The host part of UA registration entries can be masqueraded 44 | (mask_host, masked_host config items). Some Siemens SIP phones seem to 45 | need this 'feature'. 46 | - Provider specific outbound proxies can be configured 47 | - Can run "in front of" a NAT router.(in the local LAN segment) 48 | - supports "Short-Dials" 49 | - configurable RFC3581 (rport) support for sent SIP packets 50 | 51 | Plugins: 52 | - plugin_fix_fbox_anoncall 53 | This plugin attempts to work-around some SIP issues with 54 | Fritzbox devices and anonymous calls. Fritzbox devices do change their 55 | Contact header when answering an anonymous call (suppressed CLID) - this 56 | in turn confuses siproxd. This plugin attempts to work around this by 57 | sanitizing the Contact Header before processing. 58 | - plugin_siptrunk 59 | Plugin to handle SIP Trunks where using *one* single SIP account a 60 | whole number block is routed. Please read the comments in the config 61 | file section. 62 | - plugin_codecfilter 63 | Allows blacklisting of codecs and removes those from any passing SDP 64 | payload in both (incoming and outgoing) directions. This allows the 65 | proxy to force the exclusion of particular codecs in the negotiation 66 | between a local UA and a remote side. 67 | - plugin_stripheader 68 | Allows to strip particular headers from SIP messages. Useful if your 69 | provider chokes on some headers included by your local UA. 70 | - plugin_regex 71 | Applies an extended regular expression to the 'To' URI. 72 | - plugin_prefix 73 | Unconditionally prefixes all outgoing calls with a prefix. 74 | - plugin_stun 75 | Uses an external STUN server to determine the public IP 76 | address of siproxd. Useful for "in-front-of-NAT-router" 77 | scenarios. 78 | - plugin_fix_DTAG 79 | This plugin attempts to work-around some SIP issues with 80 | T-ONLINE SIP (as of 2015). T-Online.de sends broken Via headers in 81 | responses, causing the received SIP response to be discarded by 82 | any SIP client that properly checks the Via chain. 83 | - plugin_fix_bogus_via 84 | Incoming (from public network) SIP messages are checked for broken 85 | SIP Via headers. If the IP address in the latest Via Header is 86 | part of the list below, it will be replaced by the IP where the 87 | SIP message has been received from. 88 | - plugin_shortdial 89 | Quick Dial (Short Dial) 90 | Ability to define quick dial numbers that can be accessed by 91 | dialing e.g. "*01" from a local phone. 92 | 93 | Requirements: 94 | - pthreads (Linux) 95 | - glibc2 / libc5 / uClibc 96 | - libosip2 (4.x.x) 97 | 98 | Mainly tested on: 99 | - CentOS 100 | This is the main development and testing environment. Other platforms 101 | are not extensively tested. However, the code should be quite portable 102 | and build on many UNIX/Linux flavors. 103 | 104 | Builds on (tested by dev-team or reported to build): 105 | - Linux: CentOS/RedHat 106 | - FreeBSD: FreeBSD 10 107 | 108 | Reported interoperability with softphones: 109 | - SNOM series 110 | - Fritzbox UAs 111 | - Grandstream BudgeTone-100 series 112 | - Linphone (local and remote UA) (http://www.linphone.org) 113 | - Kphone (local and remote UA) (http://www.wirlab.net/kphone/) 114 | - MSN messenger 4.6 (remote and local UA) 115 | - X-Lite 116 | - SJPhone softphone 117 | - Asterisk PBX (using a SIP Trunk, masqueraded via siproxd, chan_sip driver) 118 | - Ekiga 119 | - FreePBX 120 | - Yealink series 121 | 122 | Reported interoperability with SIP service providers: 123 | - Sipgate (http://www.sipgate.de) 124 | - Stanaphone (SIP Gateway to PSTN) 125 | - Sipcall.ch (Swiss VoIP provider) 126 | - Nexphone.ch (Swiss VoIP provider - via resellers) 127 | - Ekiga 128 | - DTAG (Deutsche Telecom AG) -> requires plugin_fix_DTAG to work around 129 | some issues with this provider 130 | 131 | 132 | If you have siproxd successfully running with another SIP phone 133 | and/or service provider, please drop me a short note so I can update 134 | the list. 135 | 136 | Known interoperability issues with SIP service providers: 137 | - callcentric.com (AFAIK callcentric fails with "500 network failure" 138 | during REGISTER if more than one Via header is 139 | present in a SIP packet. Having multiple Via headers 140 | is completely in compliance with RFC3261. This might 141 | be related to their "NAT problem avoidance magic". 142 | There is nothing that can be done within siproxd 143 | to avoid this issue as callcentric does not comply 144 | with the SIP specification. 145 | 146 | 147 | 148 | Known bugs: 149 | - SRV DNS records are not yet looked up, only A records 150 | There will be more for sure... 151 | 152 | If you port siproxd to a new platform or do other kinds of changes 153 | or bugfixes that might be of general interest, please drop me a 154 | line. Also if you intend to include siproxd into a software 155 | distribution I'd be happy to get a short notice. 156 | 157 | 158 | ----- 159 | Signatures for siproxd-0.8.4.tar.gz archive: 160 | SHA-256 Hash: 161 | 162 | GnuPG signature for siproxd-0.8.4.tar.gz: 163 | 164 | 165 | NEW GPG KEY! 166 | pub 4096R/2AC27400 2017-07-11 Thomas Ries (HB9XAR) 167 | Key fingerprint = 6560 75BE 4D4D 6C4D 8005 D4B4 9D77 7F7D 2AC2 7400 168 | Key available at http://siproxd.tuxworld.ch/2AC27400.pub 169 | 170 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | TODOs, in random order: 2 | ======================= 3 | 4 | - REGISTER: updatinf the registration table 5 | currently done upon passing an REGISTER request through, independent of 6 | the outcome of the registration, the registration entry will be put into 7 | the table. 8 | IF a client now tries to register a non-existent number, a fake entry ends 9 | up in the table and may mess things up. 10 | Solution: The lifetime of a REGISTER should be set at receiving the successful 11 | REGISTER Response - before the successful response (at least initially) the 12 | entry should be regarded as invalid. 13 | 14 | 1) 15 | REGISTER request only gives 5 seconds registration time 16 | unsuccessful REGISTER response does nothing (clock ticking) 17 | successful REGISTER response gives full registration time 18 | -> this reduces the window of opportunity 19 | 20 | May want to do further: introduce negative grace time that makes REGISTER 21 | dialog mapping work, but is ignored for all other methods 22 | -> marking records as inactive upon -10 seconds (#define REGISTRATION_GRACE) 23 | -> for REGISTER dialogs, have match if active && urlmatch 24 | -> for all other dialogs, have match if active && expiration>0 && urlmatch 25 | 26 | 27 | - check via loop and private IP addresses 28 | can comment be used to store a unique ID in there? 29 | 30 | - multiple inbound interfaces - do I need to be aware of inbound at all? 31 | 32 | - Documentation (yeah, yeah...) 33 | 34 | - general security issues 35 | - security tests for received SIP messages (function securitycheck) 36 | 37 | - automagically create a proper config file during install 38 | 39 | - get_ip_by_host: reduce DNS timeouts (seems to be a more complex problem...) 40 | 41 | - via loop detection: send 482 error code 42 | 43 | - feature: don't bind to 0.0.0.0 address, but only to inbound/outbound IF's 44 | (defined by IFNAME) 45 | 46 | RFC3261 non-compliance: 47 | - Record-Route header handling 48 | 49 | - OpenBSD: Warning for redefinition of MACROS 50 | 51 | - remove URLMAP_SIZE and RTPPROXY_SIZE constants, make them configurable 52 | at runtime. 53 | 54 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run this to generate all the initial makefiles, etc. 3 | 4 | test -f configure.ac || { 5 | echo "**Error**: This directory does not look like the top-level directory" 6 | exit 1 7 | } 8 | 9 | set -e 10 | aclocal 11 | autoheader 12 | libtoolize --ltdl --copy --force 13 | automake --add-missing --copy 14 | autoconf 15 | -------------------------------------------------------------------------------- /contrib/.gitignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | Makefile.in 3 | -------------------------------------------------------------------------------- /contrib/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2002-2008 Thomas Ries 3 | # 4 | # This file is part of Siproxd. 5 | # 6 | # Siproxd is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Siproxd is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Siproxd; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | 21 | 22 | EXTRA_DIST = siproxd.init 23 | 24 | -------------------------------------------------------------------------------- /contrib/asterisk_chan_sip_xar.patch: -------------------------------------------------------------------------------- 1 | Index: chan_sip.c 2 | =================================================================== 3 | --- chan_sip.c (revision 65247) 4 | +++ chan_sip.c (working copy) 5 | @@ -1414,6 +1414,8 @@ 6 | static struct sip_peer *temp_peer(const char *name); 7 | static void register_peer_exten(struct sip_peer *peer, int onoff); 8 | static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime); 9 | +/*&&&*/ 10 | +static struct sip_peer *find_peer_siphead(const char *peer, struct sockaddr_in *sin, char *username, int realtime); 11 | static struct sip_user *find_user(const char *name, int realtime); 12 | static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_request *req); 13 | static int expire_register(void *data); 14 | @@ -2506,6 +2508,7 @@ 15 | (p->addr.sin_addr.s_addr == sin->sin_addr.s_addr))); 16 | } 17 | 18 | + 19 | /*! \brief Locate peer by name or ip address 20 | * This is used on incoming SIP message to find matching peer on ip 21 | or outgoing message to find matching peer on name */ 22 | @@ -2524,6 +2527,38 @@ 23 | return p; 24 | } 25 | 26 | +/*!&&& \brief Locate peer by username and ip address 27 | + * This is used on incoming SIP message to find matching peer on To username and sender IP */ 28 | +static struct sip_peer *find_peer_siphead(const char *peer, struct sockaddr_in *sin, char *username, int realtime) 29 | +{ 30 | + struct sip_peer *p = NULL; 31 | + 32 | + if (peer) { 33 | + return NULL; /* use find_peer instead */ 34 | + } else { 35 | + typeof((&peerl)->head) found = NULL; 36 | + ASTOBJ_CONTAINER_TRAVERSE(&peerl, !found, do { 37 | + ASTOBJ_RDLOCK(iterator); 38 | + if (!(sip_addrcmp(iterator->name, sin)) && 39 | + !(strcmp(iterator->username, username))) { 40 | + found = ASTOBJ_REF(iterator); 41 | + } 42 | + ASTOBJ_UNLOCK(iterator); 43 | + } while (0)); 44 | + p=found; 45 | + 46 | + /* fallback to old behavior */ 47 | + if (p == NULL) { 48 | + p=find_peer(peer, sin, realtime); 49 | + } 50 | + } /* if */ 51 | + 52 | + if (!p && realtime) 53 | + p = realtime_peer(peer, sin); 54 | + 55 | + return p; 56 | +} 57 | + 58 | /*! \brief Remove user object from in-memory storage */ 59 | static void sip_destroy_user(struct sip_user *user) 60 | { 61 | @@ -9008,6 +9043,7 @@ 62 | struct sip_user *user = NULL; 63 | struct sip_peer *peer; 64 | char from[256], *c; 65 | + char to[256], *ot; /*&&&*/ 66 | char *of; 67 | char rpid_num[50]; 68 | const char *rpid; 69 | @@ -9024,8 +9060,29 @@ 70 | t++; 71 | *t = '\0'; 72 | ast_copy_string(from, get_header(req, "From"), sizeof(from)); /* XXX bug in original code, overwrote string */ 73 | - if (pedanticsipchecking) 74 | + if (pedanticsipchecking) 75 | ast_uri_decode(from); 76 | + 77 | + /*&&&start: extract To: username from To field */ 78 | + ast_copy_string(to, get_header(req, "To"), sizeof(to)); /* &&& */ 79 | + if (pedanticsipchecking) { 80 | + ast_uri_decode(to); /*&&&*/ 81 | + } 82 | + ot = get_in_brackets(to); 83 | + if (strncasecmp(ot, "sip:", 4)) { 84 | + ast_log(LOG_NOTICE, "To address missing 'sip:', using it anyway\n"); 85 | + } else { 86 | + ot += 4; 87 | + } 88 | + /* Get just the username part */ 89 | + if ((c = strchr(ot, '@'))) { 90 | + *c = '\0'; 91 | + if ((c = strchr(ot, ':'))) 92 | + *c = '\0'; 93 | + } 94 | + /* ot is now the username of the From field */ 95 | + /*&&&end */ 96 | + 97 | /* XXX here tries to map the username for invite things */ 98 | memset(calleridname, 0, sizeof(calleridname)); 99 | get_calleridname(from, calleridname, sizeof(calleridname)); 100 | @@ -9184,9 +9241,22 @@ 101 | /* If peer is registered from this IP address or have this as a default 102 | IP address, this call is from the peer 103 | */ 104 | - peer = find_peer(NULL, &p->recv, 1); 105 | +/*&&& Original code is weak behavior. Lookup must be done viy SIP header data, 106 | + then - if all this fails - I may do the lookup via sender IP address. 107 | + Imagine different 2 account registered at the same provider - a lookup 108 | + purely based on sende IP address will mess up the matching between these 109 | + two accounts. 110 | +*/ 111 | + peer = find_peer_siphead(NULL, &p->recv, ot, 1); 112 | 113 | if (peer) { 114 | + /*&&&*/ 115 | + if (debug) { 116 | + ast_verbose("Found matching peer for '%s:%d [%s]'\n", 117 | + ast_inet_ntoa(p->recv.sin_addr), 118 | + ntohs(p->recv.sin_port), peer->name); 119 | + } 120 | + 121 | /* Set Frame packetization */ 122 | if (p->rtp) { 123 | ast_rtp_codec_setpref(p->rtp, &peer->prefs); 124 | @@ -14920,6 +14990,7 @@ 125 | int lockretry; 126 | 127 | memset(&req, 0, sizeof(req)); 128 | + memset(&sin, 0, sizeof(sin)); /*&&& just to be sure...*/ 129 | res = recvfrom(sipsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len); 130 | if (res < 0) { 131 | #if !defined(__FreeBSD__) 132 | -------------------------------------------------------------------------------- /contrib/siproxd.init: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # /etc/rc.d/init.d/siproxd 4 | # 5 | # Starts the siproxd daemon 6 | # 7 | # chkconfig: 345 94 80 8 | # 9 | # description: Listen and dispatch SIP messages 10 | # processname: siproxd 11 | 12 | # Source function library. 13 | . /etc/rc.d/init.d/functions 14 | 15 | [ -x /usr/sbin/siproxd ] || exit 0 16 | 17 | RETVAL=0 18 | 19 | # 20 | # See how we were called. 21 | # 22 | 23 | start() { 24 | # Check if it is already running 25 | if [ ! -f /var/lock/subsys/siproxd ]; then 26 | echo -n $"Starting sip proxy: " 27 | daemon /usr/sbin/siproxd 28 | RETVAL=$? 29 | [ $RETVAL -eq 0 ] && touch /var/lock/subsys/siproxd 30 | echo 31 | fi 32 | return $RETVAL 33 | } 34 | 35 | stop() { 36 | echo -n $"Stopping sip proxy: " 37 | killproc /usr/sbin/siproxd 38 | RETVAL=$? 39 | [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/siproxd 40 | echo 41 | return $RETVAL 42 | } 43 | 44 | 45 | restart() { 46 | stop 47 | start 48 | } 49 | 50 | reload() { 51 | trap "" SIGHUP 52 | killall -HUP siproxd 53 | } 54 | 55 | case "$1" in 56 | start) 57 | start 58 | ;; 59 | stop) 60 | stop 61 | ;; 62 | reload) 63 | reload 64 | ;; 65 | restart) 66 | restart 67 | ;; 68 | condrestart) 69 | if [ -f /var/lock/subsys/siproxd ]; then 70 | restart 71 | fi 72 | ;; 73 | status) 74 | status siproxd 75 | ;; 76 | *) 77 | echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}" 78 | exit 1 79 | esac 80 | 81 | exit $RETVAL 82 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | html 2 | pdf 3 | Makefile.in 4 | Makefile 5 | mysiproxd*.conf 6 | mysiproxd*.cfg 7 | -------------------------------------------------------------------------------- /doc/FLI4L_HOWTO.txt: -------------------------------------------------------------------------------- 1 | compiling siproxd for FLI4L 2 | =========================== 3 | 4 | 2.0.x (libc5 based): 5 | 6 | 1) LIBOSIP 7 | On an libc5 system (eg SUSE 5.3), first build and install 8 | libosip. Probably you get an error when building in file 9 | parser/port_misc.c, telling you about a non existing include 10 | file sys/unistd.h. To fix this, simply edit the .c file and 11 | replace the erroneous include statement to include 12 | instead of 13 | $ ./configure 14 | $ make 15 | $ make install 16 | 17 | 2) SIPROXD 18 | Delete the config.cache file. 19 | Configure siproxd: 20 | $ ./configure --enable-almost-static 21 | This will build siproxd statically linked against libosib, 22 | pthreads and dynamically against libc. Then 23 | $ make 24 | 25 | 26 | 27 | 28 | 29 | 2.1.x (uClibc based): 30 | Prerequisite: uClibc development enviroment installed 31 | 32 | 33 | 1) LIBOSIP 34 | Does not build very smoothly and properly. However, to link siproxd 35 | STATICALLY against libosip this procedure might work. 36 | Apply same fix to port_misc as described above. 37 | Apply the following path to configure.in 38 | ---snipp--- 39 | --- configure.in.orig Sat Jun 15 02:26:59 2002 40 | +++ configure.in Sun Mar 23 01:44:12 2003 41 | @@ -52,6 +52,38 @@ 42 | 43 | dnl declare --enable-* args and collect ac_help strings 44 | 45 | +dnl&&&&&&&&&&&&&&&&&& 46 | +dnl 47 | +dnl uClib support (only available on Linux, yet) 48 | +dnl 49 | +uclib_path="/usr/i386-linux-uclibc/" 50 | +AC_MSG_CHECKING("uClib path") 51 | +AC_ARG_WITH(uclib-path, 52 | + [ --with-uclib-path=DIR directory to uClib development], 53 | + uclib_path="$withval" ) 54 | +AC_MSG_RESULT($uclib_path) 55 | + 56 | +AC_MSG_CHECKING("build against uClib") 57 | +AC_ARG_ENABLE(uclib, 58 | + [ --enable-uclib build against a uClib], 59 | + build_uclib=$enableval, 60 | + build_uclib="no") 61 | +AC_MSG_RESULT($build_uclib) 62 | + 63 | + 64 | +if test "x$build_uclib" = "xyes"; then 65 | + 66 | +dnl export PATH=$uclib_path/bin:$PATH 67 | +dnl export UCLIBC_DEVEL_PREFIX=$uclib_path 68 | + 69 | + CC=$uclib_path/bin/i386-uclibc-gcc 70 | + LDD=$uclib_path/bin/i386-uclibc-ldd 71 | + LD=$uclib_path/bin/i386-uclibc-ld 72 | + CPPFLAGS=" -I $uclib_path/include/ $CPPFLAGS" 73 | + LIBS="-L $uclib_path/lib/ $LIBS" 74 | +fi 75 | +dnl&&&&&&&&&&&&&&&&&& 76 | + 77 | AC_ARG_ENABLE(debug, 78 | [ --disable-debug turn off debugging.], 79 | disable_debug=$enableval,disable_debug="yes") 80 | ---snipp--- 81 | 82 | Create new ./configure script 83 | $ aclocal -I scripts/ 84 | $ autoconf 85 | 86 | Configure and build libosip: 87 | $ ./configure --prefix= 88 | --with-uclib-path= 89 | --enable-uclib 90 | $ make -i clean 91 | $ make -i 92 | $ make -i install 93 | 94 | Ignore any compile errors! 95 | 96 | (This is just a very dirty hack to get libosip half way built) 97 | 98 | 2) SIPROXD 99 | Delete the config.cache file. 100 | Configure siproxd: 101 | $ ./configure --with-uclibc-path= 102 | --enable-uclibc --with-extra-includes=/include 103 | --with-extra-libs=/lib --enable-almost-static 104 | This will build siproxd statically linked against libosib and 105 | dynamically linked against uClibc. 106 | $ make 107 | 108 | "$ ldd src/siproxd" reports: 109 | libpthread.so.0 => /lib/libpthread.so.0 110 | libc.so.0 => /lib/libc.so.0 111 | ld-uClibc.so.0 => /lib/ld-uClibc.so.0 112 | 113 | Does Flifl 2.1.x include the full uClibc dynamic libraries (especially 114 | the pthreads.so)? 115 | -------------------------------------------------------------------------------- /doc/KNOWN_BUGS: -------------------------------------------------------------------------------- 1 | * REGISTER transactions: 2 | Currently siproxd does only support *one* Contact header in REGISTER 3 | transactions. If an UA does send multiple (which is legal) funny things 4 | may happen. 5 | There are one or two funnies associated with REGISTER transactions that 6 | should be mentioned: 7 | 1) There can be multiple Contact URIs in the request. It is legal 8 | (although very rare) to register multiple extensions at the same 9 | time. 10 | When multiple extensions need to be registered, they are generally 11 | registered separately. You probably don't need to worry about this 12 | for the time being, but it is probably worth bearing it in mind. 13 | 2) There can be multiple Contact URIs in the response. If more than 14 | one UA has registered for the same AOR, then the response to the 15 | REGISTER will contain all the registered AORs and their current 16 | expiry times. 17 | None or some of these may need 'unmapping'. Again, this probably 18 | isn't something you will come across that often, but knowing it can 19 | happen may save you some debugging time later. 20 | 3) The Contact in the request may contain '*'. This is used by some 21 | phones to deregister all registrations for the specified AOR. 22 | 4) Sometimes, there is no Contact in the request. This happens when 23 | a UA is querying the registration database. This is sometimes used 24 | for diagnostic purposes, although I suppose a phone could do this 25 | automatically for some reason. 26 | 5) The definitive expires time is not found in the request. This is 27 | simply a suggested value. The actual value is in the response from 28 | the registrar. 29 | For the definitive description -> RFC3261 section 10. 30 | 31 | -------------------------------------------------------------------------------- /doc/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2002-2008 Thomas Ries 3 | # 4 | # This file is part of Siproxd. 5 | # 6 | # Siproxd is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Siproxd is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Siproxd; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | 21 | # missing with older automake/autoconf packages 22 | docdir = ${datadir}/doc/${PACKAGE} 23 | 24 | SUBDIRS = 25 | 26 | EXTRA_DIST = siproxd.conf.example \ 27 | siproxd_passwd.cfg \ 28 | FAQ KNOWN_BUGS \ 29 | FLI4L_HOWTO.txt \ 30 | RFC3261_compliance.txt \ 31 | sample_cfg_budgetone.txt \ 32 | sample_cfg_x-lite.txt \ 33 | sample_asterisk.txt \ 34 | siproxd_guide.sgml 35 | # 36 | # docbook stuff 37 | # 38 | all-local: local_dirs docbook_html docbook_pdf 39 | 40 | local_dirs: 41 | mkdir -p html 42 | mkdir -p pdf 43 | 44 | docbook_html: siproxd_guide.sgml 45 | if have_docbook2html 46 | if [ html/siproxd_guide.html -ot siproxd_guide.sgml ]; then \ 47 | docbook2html -o html/ siproxd_guide.sgml; \ 48 | fi 49 | endif 50 | 51 | docbook_pdf: siproxd_guide.sgml 52 | if have_docbook2pdf 53 | if [ pdf/siproxd_guide.pdf -ot siproxd_guide.sgml ]; then \ 54 | docbook2pdf -o pdf/ siproxd_guide.sgml; \ 55 | fi 56 | endif 57 | 58 | clean-local: 59 | rm -rf html/* 60 | rm -rf pdf/* 61 | 62 | # 63 | # install local data 64 | # 65 | install-data-local: 66 | $(mkinstalldirs) $(DESTDIR)$(sysconfdir) 67 | $(INSTALL_DATA) $(srcdir)/siproxd.conf.example $(DESTDIR)$(sysconfdir)/ 68 | $(INSTALL_DATA) $(srcdir)/siproxd_passwd.cfg $(DESTDIR)$(sysconfdir)/ 69 | chmod 600 $(DESTDIR)$(sysconfdir)/siproxd_passwd.cfg 70 | $(mkinstalldirs) $(DESTDIR)$(docdir) 71 | if have_docbook2pdf 72 | $(INSTALL_DATA) $(srcdir)/pdf/* $(DESTDIR)$(docdir)/ 73 | endif 74 | if have_docbook2html 75 | $(INSTALL_DATA) $(srcdir)/html/* $(DESTDIR)$(docdir)/ 76 | endif 77 | -------------------------------------------------------------------------------- /doc/RFC3261_compliance.txt: -------------------------------------------------------------------------------- 1 | RFC3261 describes in detail for UAs and proxies how to behave. 2 | This document tries to make the link between the RFC and the 3 | code locations in siproxd where these actions are performed. 4 | 5 | 6 | 7 | Request Processing: implemented 8 | =================== 9 | Section 16.3: Request Validation 10 | 1. Reasonable Syntax yes 11 | 2. URI scheme no 12 | 3. Max-Forwards yes 13 | 4. (Optional) Loop Detection yes 14 | 5. Proxy-Require no 15 | 6. Proxy-Authorization yes 16 | 17 | Section 16.4 Route Information Preprocessing partially 18 | 19 | Section 16.5 Determining Request Targets no 20 | 21 | Section 16.6 Request Forwarding 22 | 1. Make a copy of the received request yes 23 | 2. Update the Request-URI yes 24 | 3. Update the Max-Forwards header field yes 25 | 4. Optionally add a Record-route header field value no 26 | 5. Optionally add additional header fields no 27 | 6. Postprocess routing information no 28 | 7. Determine the next-hop address, port, and transport yes 29 | 8. Add a Via header field value yes 30 | 9. Add a Content-Length header field if necessary yes 31 | 10. Forward the new request yes 32 | 11. Set timer C no 33 | 34 | Response Processing: implemented 35 | ==================== 36 | Section 16.3: Request Validation 37 | 1. Reasonable Syntax yes 38 | 2. URI scheme no 39 | 3. Max-Forwards no 40 | 4. (Optional) Loop Detection yes 41 | 5. Proxy-Require no 42 | 6. Proxy-Authorization yes 43 | 44 | Section 16.7 Response Processing n/a 45 | 46 | Section 16.11 Stateless Proxy partially 47 | Response processing as described in Section 16.7 does 48 | not apply to a proxy behaving statelessly. When a 49 | response arrives at a stateless proxy, the proxy MUST 50 | inspect the sent-by value in the first (topmost) Via 51 | header field value. If that address matches the proxy, 52 | (it equals a value this proxy has inserted into previous 53 | requests) the proxy MUST remove that header field value 54 | from the response and forward the result to the location 55 | indicated in the next Via header field value. The proxy 56 | MUST NOT add to, modify, or remove the message body. 57 | Unless specified otherwise, the proxy MUST NOT remove any 58 | other header field values. If the address does not match 59 | the proxy, the message MUST be silently discarded. 60 | -------------------------------------------------------------------------------- /doc/ReleaseProcedure.txt: -------------------------------------------------------------------------------- 1 | The following procedure shall be used to make a new release (siproxd-stable): 2 | 3 | Make the release: 4 | - check in all tested changes 5 | - update configure.ac (version number) 6 | - update ChangeLog (remove dev) 7 | - update RELNOTES 8 | Changes since last version 9 | General Overview 10 | - $ make dist 11 | - verify building on the supported plattforms (HP testdrive ?) 12 | - FreeBSD 13 | - OpenBSD 14 | - SunOS (Sparc) 15 | - Mac OS 16 | - Linux 64bit 17 | - $ make dist 18 | - calculate MD5 checksum, sha256 (shasum -a256) & GPG 19 | $ gpg --armor --detach-sig siproxd-0.8.3.tar.gz 20 | $ gpg --verify siproxd-0.8.3.tar.gz.asc siproxd-0.8.3.tar.gz 21 | - update RELNOTES with checksums 22 | - check in outstanding changes 23 | - create SVN tag 24 | $ svn cp svn://easytux.ch/siproxd/trunk \ 25 | svn://easytux.ch/siproxd/tags/rel_0_8_1 26 | - publish on SF.net 27 | publish RELNOTES as README file on sf.net 28 | - SF Webpage: 29 | - copy html documentation to SF web page 30 | - set current.inc to new version SF 31 | - text/RELNOTES 32 | - create a news entry (News announcement on SF.net) 33 | - Mailinglist announcement 34 | - copy release traballs & signature to tuxworld/siproxd/Releases/ 35 | 36 | Open new working release: 37 | - change version number in configure.ac 38 | - ChangeLog (add new dev release) 39 | - RELNOTES 40 | - check-in 41 | -------------------------------------------------------------------------------- /doc/build_FreeBSD.doc: -------------------------------------------------------------------------------- 1 | - install ports 2 | - fetch ports from GIT (pfSense) 3 | 4 | - update siproxd Makefile 5 | 6 | 7 | PORTNAME= siproxd 8 | ** PORTVERSION= 0.8.3dev1 9 | ** DISTNAME= siproxd-0.8.3dev 10 | CATEGORIES= net 11 | ** MASTER_SITES= http://siproxd.tuxworld.ch/ 12 | ** DISTFILES= siproxd-bleedingedge.tar.gz 13 | 14 | 15 | - clean dist cache 16 | rm /usr/ports/distcache/siproxd* 17 | 18 | - fetch and build checksum 19 | make makesum 20 | 21 | 22 | - build 23 | make 24 | 25 | - create package 26 | make package 27 | -> /usr/ports/packages/All/ 28 | 29 | -------------------------------------------------------------------------------- /doc/devel.txt: -------------------------------------------------------------------------------- 1 | Portability issues: 2 | 3 | 4 | FreeBSD: 5 | - #include 6 | before 7 | #include 8 | 9 | - #include 10 | before 11 | #include 12 | 13 | 14 | --- 15 | Weiterleitungen: 16 | 17 | Supported Header entfernen -> Weiterleitungen gehen nicht mehr. 18 | 19 | Supported: 100rel -> muss entfernt werden, da easybell ein Problem mit PRACK hat 20 | 21 | Supported: replaces sollte nicht entfernt werden damit Weiterleitungen 22 | funktionieren. 23 | 24 | -> Prugin Remove ausbauen, damit auch gezieht Header/key Paare entfernt werden 25 | koennen und nicht nur komplette HEader. 26 | 27 | -> Analog zu Codec Removal 28 | 29 | #### 30 | https://www.paypal.com/cgi-bin/webscr?item_name=Donation+to+siproxd+-+SIP+proxy%2Fmasquerading+daemon&cmd=_donations&business=tries%40gmx.net 31 | https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=2DN95JCWC2JLS&lc=CH&item_name=Siproxd¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted 32 | 33 | -------------------------------------------------------------------------------- /doc/sample_asterisk.txt: -------------------------------------------------------------------------------- 1 | Example Setup, Asterisk running on the same machine as siproxd (= NAT host). 2 | 3 | I use a iptables rule to redirect all outgoing SIP traffix from Asterisk 4 | to siproxd. 5 | 6 | /etc/sysconfig/iptables: 7 | ------------------------ 8 | *nat 9 | ###################################################################### 10 | # NAT: redirect locally generated packets 11 | :OUTPUT - [0:0] 12 | ######################### 13 | # 14 | # Asterisk Traffix via local siproxd. (must use DNAT to inbound IF! not REDIRECT) 15 | -A OUTPUT -o ppp+ -p udp --sport 5061 -j DNAT --to-destination 192.168.1.1:5060 16 | 17 | COMMIT 18 | 19 | 20 | 21 | 22 | /etc/asterisk/sip.conf: 23 | ----------------------- 24 | [general] 25 | context = default 26 | allowoverlap = no ; Disable overlap dialing support. (Default is yes) 27 | bindport = 5061 ; use a different port than 5060, as that port will be 28 | ; occupied by siproxd! 29 | bindaddr = 0.0.0.0 ; IP address to bind to (0.0.0.0 binds to all) 30 | srvlookup = yes ; Enable DNS SRV lookups on outbound calls 31 | 32 | ; g726 sounds very bad, useless! 33 | ; g722 is a dead end, no conversion from/to possible 34 | ; g729 sound like through a long metal tube 35 | disallow = all 36 | allow = gsm,ulaw,alaw,adpcm,speex,g729,g723 37 | autoframing = yes 38 | 39 | allowexternaldomains = yes 40 | allowexternalinvites = yes 41 | allowguest = yes 42 | allowsubscribe = no 43 | allowtransfer = yes 44 | alwaysauthreject = no 45 | autodomain = yes 46 | callevents = no 47 | compactheaders = no 48 | dumphistory = no 49 | g726nonstandard = no 50 | ignoreregexpire = no 51 | jbenable = no 52 | jbforce = no 53 | jblog = no 54 | maxcallbitrate = 384 55 | maxexpiry = 3600 56 | minexpiry = 180 57 | notifyringing = no 58 | pedantic = no 59 | promiscredir = no 60 | recordhistory = no 61 | relaxdtmf = no 62 | rtcachefriends = no 63 | rtsavesysname = no 64 | rtupdate = no 65 | sendrpid = yes 66 | sipdebug = no 67 | t1min = 100 68 | progressinband = no 69 | t38pt_udptl = no 70 | trustrpid = no 71 | usereqphone = no 72 | videosupport = no 73 | ; 74 | ; the following is required when using siproxd with local DNAT rule 75 | nat=never 76 | externip=192.168.1.1 77 | ; 78 | localnet = 192.168.0.0/16 ; my inbound network with local UAs 79 | domain = 192.168.1.1 ; inbound IP of host running Asterisk and siproxd 80 | domain = mynatfirewall ; -"- 81 | canreinvite = no 82 | 83 | useragent = PBX ; sipcall.ch (and others?) require UA string 84 | ; to be different from "AsteriskPBX" 85 | 86 | [authentication] 87 | ;---end--- 88 | 89 | 90 | /etc/asterisk/users.conf 91 | ------------------------ 92 | [general] 93 | ; 94 | ; Full name of a user 95 | ; 96 | fullname = New User 97 | userbase = 200 98 | ; 99 | ; Create voicemail mailbox and use use macro-stdexten 100 | ; 101 | hasvoicemail = yes 102 | ; 103 | ; Set voicemail mailbox 6000 password to 1234 104 | ; 105 | vmsecret = 1234 106 | ; 107 | ; Create SIP Peer 108 | ; 109 | hassip = yes 110 | hasiax = no 111 | ; 112 | ; 113 | ; Create manager entry 114 | ; 115 | hasmanager = no 116 | ; 117 | ; Remaining options are not specific to users.conf entries but are general. 118 | ; 119 | callwaiting = yes 120 | threewaycalling = yes 121 | callwaitingcallerid = yes 122 | transfer = yes 123 | canpark = yes 124 | cancallforward = yes 125 | callreturn = yes 126 | callgroup = 1 127 | pickupgroup = 1 128 | host = dynamic 129 | localextenlength = 3 130 | allow_aliasextns = no 131 | allow_an_extns = no 132 | hasagent = no 133 | hasdirectory = no 134 | 135 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 136 | ; Local SIP UAs 137 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 138 | [201] 139 | callwaiting = yes 140 | cid_number = 201 141 | context = local_sip 142 | email = email@host.xx 143 | fullname = Full Name 144 | group = 145 | hasagent = yes 146 | hasdirectory = yes 147 | hasiax = no 148 | hasmanager = no 149 | hassip = yes 150 | hasvoicemail = yes 151 | host = dynamic 152 | mailbox = 201 153 | secret = 154 | threewaycalling = yes 155 | zapchan = 156 | registeriax = no 157 | registersip = yes 158 | vmsecret = 159 | 160 | [202] 161 | callwaiting = yes 162 | cid_number = 202 163 | context = local_sip 164 | email = email@host.xx 165 | fullname = Full Name 166 | group = 167 | hasagent = yes 168 | hasdirectory = yes 169 | hasiax = no 170 | hasmanager = no 171 | hassip = yes 172 | hasvoicemail = yes 173 | host = dynamic 174 | mailbox = 202 175 | secret = 176 | threewaycalling = yes 177 | zapchan = 178 | registeriax = no 179 | registersip = yes 180 | vmsecret = 181 | 182 | 183 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 184 | ; SIP Trunks 185 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 186 | ; sipphone.com 187 | [trunk_1] 188 | disallow = all 189 | allow = gsm,ulaw,alaw,adpcm,speex,g729,g723 190 | callerid = 191 | contact = 1747669xxxx 192 | context = DID_trunk_1 193 | dialformat = ${EXTEN:1} 194 | fromdomain = proxy01.sipphone.com 195 | fromuser = 1747669xxxx 196 | group = 197 | hasexten = no 198 | hasiax = no 199 | hassip = yes 200 | host = proxy01.sipphone.com 201 | insecure = very 202 | port = 5060 203 | provider = 204 | registeriax = no 205 | registersip = yes 206 | secret = 207 | trunkname = Custom - sipphone1341 208 | trunkstyle = customvoip 209 | username = 1747669xxxx 210 | 211 | ; sipcall.ch 212 | [trunk_3] 213 | disallow = all 214 | allow = gsm,ulaw,alaw,adpcm,speex,g729,g723 215 | callerid = 216 | contact = 4132511xxxx 217 | context = DID_trunk_3 218 | dialformat = ${EXTEN:1} 219 | fromdomain = sip.backbone.ch 220 | fromuser = 4132511xxxx 221 | group = 222 | hasexten = no 223 | hasiax = no 224 | hassip = yes 225 | host = sip.backbone.ch 226 | insecure = very 227 | port = 5060 228 | provider = 229 | registeriax = no 230 | registersip = yes 231 | secret = 232 | trunkname = Custom - sipcall 233 | trunkstyle = customvoip 234 | username = 4132511xxxx 235 | 236 | ;---end--- 237 | -------------------------------------------------------------------------------- /doc/sample_cfg_budgetone.txt: -------------------------------------------------------------------------------- 1 | 2 | Grandstream IP Phone Configuration 3 | 4 | MAC Address: 00.0B.82.00.31.89 5 | Software Version: Program--1.0.3.81 Bootloader--1.0.0.7 6 | HTML--1.0.0.18 7 | detected firewall/NAT type is open Internet 8 | 9 | Admin Password: **********____________________ (password to 10 | configure this IP phone) 11 | IP Address: 12 | (*) dynamically assigned via DHCP, or 13 | (_) statically configured as: 14 | IP Address: ___. ___. ___. ___ 15 | Subnet Mask: ___. ___. ___. ___ 16 | Default Router: ___. ___. ___. ___ 17 | DNS Server 1: ___. ___. ___. ___ 18 | DNS Server 2: ___. ___. ___. ___ 19 | SIP Server: proxy01.sipphone.com__________ (e.g., sip.mycompany.com, 20 | or IP address) 21 | Outbound Proxy: ____________ (e.g., 22 | proxy.myprovider.com, or IP address, if any) 23 | SIP User ID: 1747669****__________ (the user part of an SIP 24 | address) 25 | Authenticate ID: 1747669****__________ (can be identical to 26 | or different from SIP User ID) 27 | Authenticate Password: ______________________________ 28 | Name: your name_____________________ (optional, e.g., John Doe) 29 | 30 | Advanced Options: 31 | Preferred Vocoder: 32 | (in listed order) choice 1: [current setting is "G729"] 33 | choice 2: [current setting is "PCMA"] 34 | choice 3: [current setting is "G723"] 35 | choice 4: [current setting is "PCMU"] 36 | choice 5: [current setting is "G726-32"] 37 | choice 6: [current setting is "G728"] 38 | G723 rate: (*) 6.3kbps encoding rate (_) 5.3kbps encoding rate 39 | Silence Suppression: (*) No (_) Yes 40 | Voice Frames per TX: ______1 (up to 10/20/32/64 frames for 41 | G711/G726/G723/other codecs respectively) 42 | IP QoS: 48_____ (IP Diff-Serv or Precedence value for RTP) 43 | VLAN Tag: 0______ (VLAN classification for RTP) 44 | SIP User ID is 45 | phone number: (*) No (_) Yes 46 | Dial Plan: _______ (dial plan prefix string) 47 | SIP Registration: (*) Yes (_) No 48 | Register Expiration: 30_____ (in minutes. default 1 hour, max 45 49 | days) 50 | Early Dial: (*) No (_) Yes (use "Yes" only if proxy supports 51 | 484 response) 52 | Use # as Dial Key: (*) No (_) Yes (if set to Yes, "#" will 53 | function as the "(Re-)Dial" key) 54 | local SIP port: 5060___ (default 5060) 55 | local RTP port: 5004___ (1024-65535, default 5004) 56 | Use random port: (_) No (*) Yes 57 | NAT Traversal: (*) No 58 | (_) Yes, STUN server is: ________________________________ (URI or 59 | IP:port) 60 | TFTP Server: 4__. 3__. 153. _56 (for remote software upgrade and 61 | configuration) 62 | Voice Mail UserID: 1747669****__________ (User ID/extension 63 | for 3rd party voice mail system) 64 | Offhook Auto-Dial: ______________________________ (User ID/extension 65 | to dial automatically when offhook) 66 | Send DTMF: (*) in-audio (_) via RTP (RFC2833) (_) via SIP 67 | INFO 68 | DTMF Payload Type: 101____ 69 | Send Flash Event: (*) No (_) Yes (Flash will be sent as a 70 | DTMF event if set to Yes) 71 | NTP Server: ________ (URI or IP address) 72 | Time Zone: 73 | [current setting is "GMT+1:00 (Paris, Amsterdam, Berlin, Rome, Vienna, 74 | Madrid, Warsaw, Brussels)"] 75 | Daylight Savings Time: (*) No (_) Yes (if set to Yes, display 76 | time will be 1 hour ahead of normal time) 77 | Send Anonymous: (*) No (_) Yes (caller ID will be blocked if 78 | set to Yes) 79 | Update [BUTTON] [BUTTON] 80 | -------------------------------------------------------------------------------- /doc/sample_cfg_x-lite.txt: -------------------------------------------------------------------------------- 1 | X-Lite - Private Build 1103a 2 | 3 | 4 | Local registration at siproxd 5 | ============================= 6 | 7 | System Settings 8 | Network 9 | Autodetect IP: Yes 10 | Listen on IP: - 11 | ** Use X-NAT to Choose SIP/RTP Ports: Never 12 | Listen SIP Port: 5060 13 | Listenm RTP Port: 8000 14 | NAT Firewall IP: - 15 | ** Out Bound SIP Proxy: 16 | ** Force Firewall Type: Open IP 17 | Primary STUN Server: - 18 | Secondary STUN Server: - 19 | Primary DNS Server: - 20 | Secondary DNS Server: - 21 | Provider DNS Server: - 22 | 23 | ** SIP Proxy 24 | Enabled: Yes 25 | Display Name: Default 26 | Username: 27 | Authorization User: 28 | Password: 29 | 1) Domain/Realm: 30 | SIP Proxy: 31 | Out Bound Proxy: 32 | Use Out Bound Proxy: Always 33 | Send Internal IP: Default 34 | Register: Always 35 | Voicemail SIP URL: - 36 | Forward SIP URL: - 37 | Use Voicemail: Forward to Voicemail 38 | Direct Diap IP: No 39 | Dial Prefix: - 40 | Provider Website (if applicabla): - 41 | Update Settings (if applicable): - 42 | 43 | X-Tunnels 44 | Use X-Tunnels: Never 45 | 46 | X-Cipher 47 | Use X-Cipher: Never 48 | 49 | Advanced System Settings: 50 | SIP Settings 51 | Reregister Proxy(s): 1800 52 | ** Send UDP Keep-alive Messages to Proxy: No 53 | Frequency to send UDP keep-alive Messages to proxy (ms): 10000 54 | Send Compact SIP Messages: No 55 | Send Basic SDP Messages: No 56 | Use SIP rport: Yes 57 | Obey Reverse UDP Rules: Yes 58 | Should Timeout SIP Messages After (ms): 9000 59 | Should Timeout Bye SIP Message After (ms): 4000 60 | Should Timeout Provisional SIP Relpies After (ms): 40000 61 | Should Wait to Resend Request After Provisional Reply (ms): 10000 62 | Should Resend SIP Messages After (ms): 1500 63 | 64 | RTP Settings 65 | RTP Keep-alive Settings 66 | Send RTP Keep-alive Messages: Yes 67 | Send RTP Keep-alive Messages Frequency (ms): 15000 68 | RTP Keep-alive Bogus Payload Type: 13 69 | Secure Magic Number: 128 70 | Obey Reverse UDP Mapping Rules: Yes 71 | ** Send RTCP Messages: No 72 | 73 | 74 | 1) must be a hostname that resolves to the public IP address 75 | siproxd uses (outbound interface) 76 | 77 | Codec Settings 78 | g711u 79 | Enabled: Yes 80 | Magic Number: 0 81 | Samples Per Frame: 160 82 | DTMF Samples per Frame: 160 83 | DTMF Prefix Force On: - 84 | DTMF Prefix Force Off: - 85 | g711a 86 | Enabled: Yes 87 | Magic Number: 8 88 | Samples Per Frame: 160 89 | DTMF Samples per Frame: 160 90 | DTMF Prefix Force On: - 91 | DTMF Prefix Force Off: - 92 | gsm 93 | Enabled: No 94 | Magic Number: 3 95 | Samples Per Frame: 160 96 | DTMF Prefix Force On: - 97 | DTMF Prefix Force Off: - 98 | iLBC 99 | Enabled: No 100 | Magic Number: 98 101 | Samples Per Frame: 240 102 | DTMF Prefix Force On: - 103 | DTMF Prefix Force Off: - 104 | Speex 105 | Enabled: No 106 | Magic Number: 97 107 | Speex Quality: 97 108 | Speex Complexity: 4 109 | DTMF Prefix Force On: - 110 | DTMF Prefix Force Off: - 111 | 112 | Codec Order 113 | g711u: 4 114 | g711a: 5 115 | gsm: 3 116 | iLBC: 1 117 | Speex: 2 118 | 119 | 120 | Remote registration at 3rd party registrar 121 | ========================================== 122 | 123 | System Settings 124 | ** SIP Proxy 125 | Enabled: Yes 126 | Display Name: Default 127 | Username: 128 | Authorization User: 129 | Password: 130 | Domain/Realm: 131 | SIP Proxy: 132 | Out Bound Proxy: 133 | Use Out Bound Proxy: Always 134 | Send Internal IP: Default 135 | Register: Always 136 | Voicemail SIP URL: - 137 | Forward SIP URL: - 138 | Use Voicemail: Forward to Voicemail 139 | Direct Diap IP: No 140 | Dial Prefix: - 141 | Provider Website (if applicabla): - 142 | Update Settings (if applicable): - 143 | -------------------------------------------------------------------------------- /doc/siproxd_passwd.cfg: -------------------------------------------------------------------------------- 1 | ###################################################################### 2 | # 3 | # Per user password file for siproxd 4 | # 5 | # format is: 6 | # 7 | # username and password must not contains white spaces 8 | # 9 | ###################################################################### 10 | user password 11 | -------------------------------------------------------------------------------- /scripts/.gitignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | Makefile.in 3 | ltmain.sh 4 | -------------------------------------------------------------------------------- /scripts/compile: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Wrapper for compilers which do not understand '-c -o'. 3 | 4 | scriptversion=2018-03-07.03; # UTC 5 | 6 | # Copyright (C) 1999-2018 Free Software Foundation, Inc. 7 | # Written by Tom Tromey . 8 | # 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | # This file is maintained in Automake, please report 28 | # bugs to or send patches to 29 | # . 30 | 31 | nl=' 32 | ' 33 | 34 | # We need space, tab and new line, in precisely that order. Quoting is 35 | # there to prevent tools from complaining about whitespace usage. 36 | IFS=" "" $nl" 37 | 38 | file_conv= 39 | 40 | # func_file_conv build_file lazy 41 | # Convert a $build file to $host form and store it in $file 42 | # Currently only supports Windows hosts. If the determined conversion 43 | # type is listed in (the comma separated) LAZY, no conversion will 44 | # take place. 45 | func_file_conv () 46 | { 47 | file=$1 48 | case $file in 49 | / | /[!/]*) # absolute file, and not a UNC file 50 | if test -z "$file_conv"; then 51 | # lazily determine how to convert abs files 52 | case `uname -s` in 53 | MINGW*) 54 | file_conv=mingw 55 | ;; 56 | CYGWIN*) 57 | file_conv=cygwin 58 | ;; 59 | *) 60 | file_conv=wine 61 | ;; 62 | esac 63 | fi 64 | case $file_conv/,$2, in 65 | *,$file_conv,*) 66 | ;; 67 | mingw/*) 68 | file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` 69 | ;; 70 | cygwin/*) 71 | file=`cygpath -m "$file" || echo "$file"` 72 | ;; 73 | wine/*) 74 | file=`winepath -w "$file" || echo "$file"` 75 | ;; 76 | esac 77 | ;; 78 | esac 79 | } 80 | 81 | # func_cl_dashL linkdir 82 | # Make cl look for libraries in LINKDIR 83 | func_cl_dashL () 84 | { 85 | func_file_conv "$1" 86 | if test -z "$lib_path"; then 87 | lib_path=$file 88 | else 89 | lib_path="$lib_path;$file" 90 | fi 91 | linker_opts="$linker_opts -LIBPATH:$file" 92 | } 93 | 94 | # func_cl_dashl library 95 | # Do a library search-path lookup for cl 96 | func_cl_dashl () 97 | { 98 | lib=$1 99 | found=no 100 | save_IFS=$IFS 101 | IFS=';' 102 | for dir in $lib_path $LIB 103 | do 104 | IFS=$save_IFS 105 | if $shared && test -f "$dir/$lib.dll.lib"; then 106 | found=yes 107 | lib=$dir/$lib.dll.lib 108 | break 109 | fi 110 | if test -f "$dir/$lib.lib"; then 111 | found=yes 112 | lib=$dir/$lib.lib 113 | break 114 | fi 115 | if test -f "$dir/lib$lib.a"; then 116 | found=yes 117 | lib=$dir/lib$lib.a 118 | break 119 | fi 120 | done 121 | IFS=$save_IFS 122 | 123 | if test "$found" != yes; then 124 | lib=$lib.lib 125 | fi 126 | } 127 | 128 | # func_cl_wrapper cl arg... 129 | # Adjust compile command to suit cl 130 | func_cl_wrapper () 131 | { 132 | # Assume a capable shell 133 | lib_path= 134 | shared=: 135 | linker_opts= 136 | for arg 137 | do 138 | if test -n "$eat"; then 139 | eat= 140 | else 141 | case $1 in 142 | -o) 143 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 144 | eat=1 145 | case $2 in 146 | *.o | *.[oO][bB][jJ]) 147 | func_file_conv "$2" 148 | set x "$@" -Fo"$file" 149 | shift 150 | ;; 151 | *) 152 | func_file_conv "$2" 153 | set x "$@" -Fe"$file" 154 | shift 155 | ;; 156 | esac 157 | ;; 158 | -I) 159 | eat=1 160 | func_file_conv "$2" mingw 161 | set x "$@" -I"$file" 162 | shift 163 | ;; 164 | -I*) 165 | func_file_conv "${1#-I}" mingw 166 | set x "$@" -I"$file" 167 | shift 168 | ;; 169 | -l) 170 | eat=1 171 | func_cl_dashl "$2" 172 | set x "$@" "$lib" 173 | shift 174 | ;; 175 | -l*) 176 | func_cl_dashl "${1#-l}" 177 | set x "$@" "$lib" 178 | shift 179 | ;; 180 | -L) 181 | eat=1 182 | func_cl_dashL "$2" 183 | ;; 184 | -L*) 185 | func_cl_dashL "${1#-L}" 186 | ;; 187 | -static) 188 | shared=false 189 | ;; 190 | -Wl,*) 191 | arg=${1#-Wl,} 192 | save_ifs="$IFS"; IFS=',' 193 | for flag in $arg; do 194 | IFS="$save_ifs" 195 | linker_opts="$linker_opts $flag" 196 | done 197 | IFS="$save_ifs" 198 | ;; 199 | -Xlinker) 200 | eat=1 201 | linker_opts="$linker_opts $2" 202 | ;; 203 | -*) 204 | set x "$@" "$1" 205 | shift 206 | ;; 207 | *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) 208 | func_file_conv "$1" 209 | set x "$@" -Tp"$file" 210 | shift 211 | ;; 212 | *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) 213 | func_file_conv "$1" mingw 214 | set x "$@" "$file" 215 | shift 216 | ;; 217 | *) 218 | set x "$@" "$1" 219 | shift 220 | ;; 221 | esac 222 | fi 223 | shift 224 | done 225 | if test -n "$linker_opts"; then 226 | linker_opts="-link$linker_opts" 227 | fi 228 | exec "$@" $linker_opts 229 | exit 1 230 | } 231 | 232 | eat= 233 | 234 | case $1 in 235 | '') 236 | echo "$0: No command. Try '$0 --help' for more information." 1>&2 237 | exit 1; 238 | ;; 239 | -h | --h*) 240 | cat <<\EOF 241 | Usage: compile [--help] [--version] PROGRAM [ARGS] 242 | 243 | Wrapper for compilers which do not understand '-c -o'. 244 | Remove '-o dest.o' from ARGS, run PROGRAM with the remaining 245 | arguments, and rename the output as expected. 246 | 247 | If you are trying to build a whole package this is not the 248 | right script to run: please start by reading the file 'INSTALL'. 249 | 250 | Report bugs to . 251 | EOF 252 | exit $? 253 | ;; 254 | -v | --v*) 255 | echo "compile $scriptversion" 256 | exit $? 257 | ;; 258 | cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ 259 | icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) 260 | func_cl_wrapper "$@" # Doesn't return... 261 | ;; 262 | esac 263 | 264 | ofile= 265 | cfile= 266 | 267 | for arg 268 | do 269 | if test -n "$eat"; then 270 | eat= 271 | else 272 | case $1 in 273 | -o) 274 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 275 | # So we strip '-o arg' only if arg is an object. 276 | eat=1 277 | case $2 in 278 | *.o | *.obj) 279 | ofile=$2 280 | ;; 281 | *) 282 | set x "$@" -o "$2" 283 | shift 284 | ;; 285 | esac 286 | ;; 287 | *.c) 288 | cfile=$1 289 | set x "$@" "$1" 290 | shift 291 | ;; 292 | *) 293 | set x "$@" "$1" 294 | shift 295 | ;; 296 | esac 297 | fi 298 | shift 299 | done 300 | 301 | if test -z "$ofile" || test -z "$cfile"; then 302 | # If no '-o' option was seen then we might have been invoked from a 303 | # pattern rule where we don't need one. That is ok -- this is a 304 | # normal compilation that the losing compiler can handle. If no 305 | # '.c' file was seen then we are probably linking. That is also 306 | # ok. 307 | exec "$@" 308 | fi 309 | 310 | # Name of file we expect compiler to create. 311 | cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` 312 | 313 | # Create the lock directory. 314 | # Note: use '[/\\:.-]' here to ensure that we don't use the same name 315 | # that we are using for the .o file. Also, base the name on the expected 316 | # object file name, since that is what matters with a parallel build. 317 | lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d 318 | while true; do 319 | if mkdir "$lockdir" >/dev/null 2>&1; then 320 | break 321 | fi 322 | sleep 1 323 | done 324 | # FIXME: race condition here if user kills between mkdir and trap. 325 | trap "rmdir '$lockdir'; exit 1" 1 2 15 326 | 327 | # Run the compile. 328 | "$@" 329 | ret=$? 330 | 331 | if test -f "$cofile"; then 332 | test "$cofile" = "$ofile" || mv "$cofile" "$ofile" 333 | elif test -f "${cofile}bj"; then 334 | test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" 335 | fi 336 | 337 | rmdir "$lockdir" 338 | exit $ret 339 | 340 | # Local Variables: 341 | # mode: shell-script 342 | # sh-indentation: 2 343 | # eval: (add-hook 'before-save-hook 'time-stamp) 344 | # time-stamp-start: "scriptversion=" 345 | # time-stamp-format: "%:y-%02m-%02d.%02H" 346 | # time-stamp-time-zone: "UTC0" 347 | # time-stamp-end: "; # UTC" 348 | # End: 349 | -------------------------------------------------------------------------------- /scripts/missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common wrapper for a few potentially missing GNU programs. 3 | 4 | scriptversion=2018-03-07.03; # UTC 5 | 6 | # Copyright (C) 1996-2018 Free Software Foundation, Inc. 7 | # Originally written by Fran,cois Pinard , 1996. 8 | 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | if test $# -eq 0; then 28 | echo 1>&2 "Try '$0 --help' for more information" 29 | exit 1 30 | fi 31 | 32 | case $1 in 33 | 34 | --is-lightweight) 35 | # Used by our autoconf macros to check whether the available missing 36 | # script is modern enough. 37 | exit 0 38 | ;; 39 | 40 | --run) 41 | # Back-compat with the calling convention used by older automake. 42 | shift 43 | ;; 44 | 45 | -h|--h|--he|--hel|--help) 46 | echo "\ 47 | $0 [OPTION]... PROGRAM [ARGUMENT]... 48 | 49 | Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due 50 | to PROGRAM being missing or too old. 51 | 52 | Options: 53 | -h, --help display this help and exit 54 | -v, --version output version information and exit 55 | 56 | Supported PROGRAM values: 57 | aclocal autoconf autoheader autom4te automake makeinfo 58 | bison yacc flex lex help2man 59 | 60 | Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 61 | 'g' are ignored when checking the name. 62 | 63 | Send bug reports to ." 64 | exit $? 65 | ;; 66 | 67 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 68 | echo "missing $scriptversion (GNU Automake)" 69 | exit $? 70 | ;; 71 | 72 | -*) 73 | echo 1>&2 "$0: unknown '$1' option" 74 | echo 1>&2 "Try '$0 --help' for more information" 75 | exit 1 76 | ;; 77 | 78 | esac 79 | 80 | # Run the given program, remember its exit status. 81 | "$@"; st=$? 82 | 83 | # If it succeeded, we are done. 84 | test $st -eq 0 && exit 0 85 | 86 | # Also exit now if we it failed (or wasn't found), and '--version' was 87 | # passed; such an option is passed most likely to detect whether the 88 | # program is present and works. 89 | case $2 in --version|--help) exit $st;; esac 90 | 91 | # Exit code 63 means version mismatch. This often happens when the user 92 | # tries to use an ancient version of a tool on a file that requires a 93 | # minimum version. 94 | if test $st -eq 63; then 95 | msg="probably too old" 96 | elif test $st -eq 127; then 97 | # Program was missing. 98 | msg="missing on your system" 99 | else 100 | # Program was found and executed, but failed. Give up. 101 | exit $st 102 | fi 103 | 104 | perl_URL=https://www.perl.org/ 105 | flex_URL=https://github.com/westes/flex 106 | gnu_software_URL=https://www.gnu.org/software 107 | 108 | program_details () 109 | { 110 | case $1 in 111 | aclocal|automake) 112 | echo "The '$1' program is part of the GNU Automake package:" 113 | echo "<$gnu_software_URL/automake>" 114 | echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" 115 | echo "<$gnu_software_URL/autoconf>" 116 | echo "<$gnu_software_URL/m4/>" 117 | echo "<$perl_URL>" 118 | ;; 119 | autoconf|autom4te|autoheader) 120 | echo "The '$1' program is part of the GNU Autoconf package:" 121 | echo "<$gnu_software_URL/autoconf/>" 122 | echo "It also requires GNU m4 and Perl in order to run:" 123 | echo "<$gnu_software_URL/m4/>" 124 | echo "<$perl_URL>" 125 | ;; 126 | esac 127 | } 128 | 129 | give_advice () 130 | { 131 | # Normalize program name to check for. 132 | normalized_program=`echo "$1" | sed ' 133 | s/^gnu-//; t 134 | s/^gnu//; t 135 | s/^g//; t'` 136 | 137 | printf '%s\n' "'$1' is $msg." 138 | 139 | configure_deps="'configure.ac' or m4 files included by 'configure.ac'" 140 | case $normalized_program in 141 | autoconf*) 142 | echo "You should only need it if you modified 'configure.ac'," 143 | echo "or m4 files included by it." 144 | program_details 'autoconf' 145 | ;; 146 | autoheader*) 147 | echo "You should only need it if you modified 'acconfig.h' or" 148 | echo "$configure_deps." 149 | program_details 'autoheader' 150 | ;; 151 | automake*) 152 | echo "You should only need it if you modified 'Makefile.am' or" 153 | echo "$configure_deps." 154 | program_details 'automake' 155 | ;; 156 | aclocal*) 157 | echo "You should only need it if you modified 'acinclude.m4' or" 158 | echo "$configure_deps." 159 | program_details 'aclocal' 160 | ;; 161 | autom4te*) 162 | echo "You might have modified some maintainer files that require" 163 | echo "the 'autom4te' program to be rebuilt." 164 | program_details 'autom4te' 165 | ;; 166 | bison*|yacc*) 167 | echo "You should only need it if you modified a '.y' file." 168 | echo "You may want to install the GNU Bison package:" 169 | echo "<$gnu_software_URL/bison/>" 170 | ;; 171 | lex*|flex*) 172 | echo "You should only need it if you modified a '.l' file." 173 | echo "You may want to install the Fast Lexical Analyzer package:" 174 | echo "<$flex_URL>" 175 | ;; 176 | help2man*) 177 | echo "You should only need it if you modified a dependency" \ 178 | "of a man page." 179 | echo "You may want to install the GNU Help2man package:" 180 | echo "<$gnu_software_URL/help2man/>" 181 | ;; 182 | makeinfo*) 183 | echo "You should only need it if you modified a '.texi' file, or" 184 | echo "any other file indirectly affecting the aspect of the manual." 185 | echo "You might want to install the Texinfo package:" 186 | echo "<$gnu_software_URL/texinfo/>" 187 | echo "The spurious makeinfo call might also be the consequence of" 188 | echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" 189 | echo "want to install GNU make:" 190 | echo "<$gnu_software_URL/make/>" 191 | ;; 192 | *) 193 | echo "You might have modified some files without having the proper" 194 | echo "tools for further handling them. Check the 'README' file, it" 195 | echo "often tells you about the needed prerequisites for installing" 196 | echo "this package. You may also peek at any GNU archive site, in" 197 | echo "case some other package contains this missing '$1' program." 198 | ;; 199 | esac 200 | } 201 | 202 | give_advice "$1" | sed -e '1s/^/WARNING: /' \ 203 | -e '2,$s/^/ /' >&2 204 | 205 | # Propagate the correct exit status (expected to be 127 for a program 206 | # not found, 63 for a program that failed due to version mismatch). 207 | exit $st 208 | 209 | # Local variables: 210 | # eval: (add-hook 'before-save-hook 'time-stamp) 211 | # time-stamp-start: "scriptversion=" 212 | # time-stamp-format: "%:y-%02m-%02d.%02H" 213 | # time-stamp-time-zone: "UTC0" 214 | # time-stamp-end: "; # UTC" 215 | # End: 216 | -------------------------------------------------------------------------------- /siproxd.spec.in: -------------------------------------------------------------------------------- 1 | %define name @PACKAGE@ 2 | %define ver @VERSION@ 3 | %define release 1 4 | %define serial 1 5 | %define prefix %{_prefix} 6 | %define sysconfdir /etc 7 | %define piddir /var/run/siproxd/ 8 | %define regdir /var/lib/siproxd/ 9 | %define siproxduser %{name} 10 | 11 | Name: %{name} 12 | Summary: A SIP masquerading proxy with RTP support 13 | Version: %{ver} 14 | Release: %{release} 15 | License: GPL, (c) 2002-2011 Thomas Ries 16 | Group: Applications/Communications 17 | Source0: %{name}-%{ver}.tar.gz 18 | 19 | URL: http://siproxd.sourceforge.net/ 20 | BuildRoot: %{_tmppath}/%{name}-%{ver}-root 21 | 22 | Requires: libosip2 >= 3.0.0 23 | BuildRequires: libosip2 >= 3.0.0 24 | BuildRequires: libosip2-devel >= 3.0.0 25 | 26 | Vendor: Thomas Ries 27 | 28 | Packager: Thomas Ries 29 | 30 | %description 31 | Siproxd is a proxy/masquerading daemon for SIP (Session Initiation 32 | Protocol), which is used in IP telephony. 33 | It handles registrations of SIP clients on a private IP network 34 | and performs rewriting of the SIP message bodies to make SIP 35 | connections work via a masquerading firewall (NAT). 36 | It allows SIP software clients (like kphone, linphone) or SIP 37 | hardware clients (Voice over IP phones which are SIP-compatible, 38 | such as those from Cisco, Grandstream or Snom) to work behind 39 | an IP masquerading firewall or NAT router. 40 | 41 | 42 | %prep 43 | %setup -q 44 | 45 | 46 | %build 47 | CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{prefix} \ 48 | --sysconfdir=%{sysconfdir} \ 49 | --disable-doc 50 | make 51 | 52 | 53 | %install 54 | make prefix=$RPM_BUILD_ROOT%{prefix} \ 55 | sysconfdir=$RPM_BUILD_ROOT%{sysconfdir} \ 56 | install 57 | mv %{buildroot}%{sysconfdir}/siproxd.conf.example \ 58 | %{buildroot}%{sysconfdir}/siproxd.conf 59 | 60 | # edit siproxd.conf and put correct username 61 | sed -i "s/user\ =\ nobody/user\ =\ %{siproxduser}/" \ 62 | %{buildroot}%{sysconfdir}/siproxd.conf 63 | 64 | # will be added separately below 65 | rm -r %{buildroot}%{_defaultdocdir}/%{name} 66 | 67 | install -d %{buildroot}%{_initrddir}/ 68 | install contrib/siproxd.init %{buildroot}%{_initrddir}/siproxd 69 | 70 | install -d %{buildroot}%{piddir} 71 | install -d %{buildroot}%{regdir} 72 | 73 | 74 | %clean 75 | rm -rf %{buildroot} 76 | 77 | 78 | %files 79 | %defattr(-, root, root) 80 | %doc COPYING README AUTHORS INSTALL NEWS ChangeLog 81 | %doc doc/FAQ doc/FLI4L_HOWTO.txt doc/sample_*.txt 82 | 83 | %attr(0755,root,root) %{_sbindir}/siproxd 84 | %config %{sysconfdir}/siproxd.conf 85 | %config %{sysconfdir}/siproxd_passwd.cfg 86 | %attr(0755,root,root) %{_initrddir}/siproxd 87 | %attr(0755,root,root) %{_libdir}/%{name}/ 88 | 89 | %attr(0700,%{siproxduser},root) %{piddir} 90 | %attr(0700,%{siproxduser},root) %{regdir} 91 | 92 | 93 | %pre 94 | getent group %{siproxduser} &>/dev/null || groupadd -r %{siproxduser} 95 | getent passwd %{siproxduser} &>/dev/null || \ 96 | /usr/sbin/useradd -r -g %{siproxduser} -s /sbin/nologin -c %{siproxduser} \ 97 | -d %{regdir} %{siproxduser} 98 | 99 | 100 | %post 101 | echo "Edit the config file %{sysconfigdir}/siproxd.conf!" 102 | /sbin/chkconfig --add %{name} 103 | 104 | 105 | %preun 106 | if [ $1 = 0 ]; then 107 | /sbin/service %{name} stop 108 | /sbin/chkconfig --del %{name} 109 | fi 110 | 111 | 112 | %changelog 113 | * Fri Oct 09 2004 Thomas Ries 114 | - startup script in /etc/rc.d/init.d/siproxd 115 | - create directories for PID and registration files 116 | 117 | * Fri Oct 31 2003 Thomas Ries 118 | - siproxd is now installed to sbin directory 119 | 120 | * Fri Oct 24 2003 Thomas Ries 121 | - added config files and some more doc files 122 | - rename sample config file and remind user to edit it. 123 | - minor cleanup 124 | 125 | * Sat Aug 30 2003 Thomas Ries 126 | - always use /etc as sysconfdir 127 | 128 | * Sat Sep 21 2002 Thomas Ries 129 | - first RPM support 130 | 131 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | Makefile.in 3 | .deps 4 | .buildno 5 | .libs 6 | *.o 7 | *.a 8 | *.la 9 | *.lo 10 | siproxd 11 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2002-2022 Thomas Ries 3 | # 4 | # This file is part of Siproxd. 5 | # 6 | # Siproxd is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Siproxd is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Siproxd; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | 21 | # some magic for reproducible builds 22 | if HAVE_SOURCE_DATE_EPOCH 23 | BUILDDATE="\"`date -d @$(SOURCE_DATE_EPOCH) -u '+%Y-%m-%dT%H:%M:%S'`\"" 24 | BUILDSTR="\"none\"" 25 | else 26 | if REPRODUCIBLE_BUILD 27 | BUILDDATE="\"unknown\"" 28 | BUILDSTR="\"none\"" 29 | else 30 | BUILDDATE="\"`date -u '+%Y-%m-%dT%H:%M:%S'`\"" 31 | BUILDSTR="\"`cat .buildno`\"" 32 | endif 33 | endif 34 | 35 | AM_CFLAGS = -D_GNU_SOURCE $(LTDLDEF) \ 36 | -Werror-implicit-function-declaration \ 37 | -DBUILDSTR=$(BUILDSTR) \ 38 | -DBUILDDATE=$(BUILDDATE) 39 | #&&&INCLUDES = $(LTDLINCL) 40 | AM_CPPFLAGS = $(LTDLINCL) 41 | 42 | # 43 | # Plugin modules, installed in "pkglib" directory ($prefix/lib/siproxd/) 44 | # 45 | pkglib_LTLIBRARIES = plugin_demo.la \ 46 | plugin_shortdial.la \ 47 | plugin_logcall.la \ 48 | plugin_defaulttarget.la \ 49 | plugin_fix_bogus_via.la \ 50 | plugin_fix_DTAG.la \ 51 | plugin_stun.la \ 52 | plugin_prefix.la \ 53 | plugin_regex.la \ 54 | plugin_regex_body.la \ 55 | plugin_codecfilter.la \ 56 | plugin_stripheader.la \ 57 | plugin_siptrunk.la \ 58 | plugin_fix_fbox_anoncall.la \ 59 | plugin_stats.la \ 60 | plugin_blacklist.la 61 | 62 | DLOPENPLUGINS = -dlopen plugin_demo.la \ 63 | -dlopen plugin_shortdial.la \ 64 | -dlopen plugin_logcall.la \ 65 | -dlopen plugin_defaulttarget.la \ 66 | -dlopen plugin_fix_bogus_via.la \ 67 | -dlopen plugin_fix_DTAG.la \ 68 | -dlopen plugin_stun.la \ 69 | -dlopen plugin_prefix.la \ 70 | -dlopen plugin_regex.la \ 71 | -dlopen plugin_regex_body.la \ 72 | -dlopen plugin_codecfilter.la \ 73 | -dlopen plugin_stripheader.la \ 74 | -dlopen plugin_siptrunk.la \ 75 | -dlopen plugin_fix_fbox_anoncall.la \ 76 | -dlopen plugin_stats.la \ 77 | -dlopen plugin_blacklist.la 78 | # 79 | plugin_demo_la_SOURCES = plugin_demo.c 80 | plugin_demo_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 81 | # 82 | plugin_shortdial_la_SOURCES = plugin_shortdial.c 83 | plugin_shortdial_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 84 | # 85 | plugin_logcall_la_SOURCES = plugin_logcall.c 86 | plugin_logcall_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 87 | # 88 | plugin_defaulttarget_la_SOURCES = plugin_defaulttarget.c 89 | plugin_defaulttarget_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 90 | # 91 | plugin_fix_bogus_via_la_SOURCES = plugin_fix_bogus_via.c 92 | plugin_fix_bogus_via_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 93 | # 94 | plugin_fix_DTAG_la_SOURCES = plugin_fix_DTAG.c 95 | plugin_fix_DTAG_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 96 | # 97 | plugin_stun_la_SOURCES = plugin_stun.c 98 | plugin_stun_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 99 | # 100 | plugin_prefix_la_SOURCES = plugin_prefix.c 101 | plugin_prefix_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 102 | # 103 | plugin_regex_la_SOURCES = plugin_regex.c 104 | plugin_regex_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 105 | # 106 | plugin_regex_body_la_SOURCES = plugin_regex_body.c 107 | plugin_regex_body_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 108 | # 109 | plugin_codecfilter_la_SOURCES = plugin_codecfilter.c 110 | plugin_codecfilter_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 111 | # 112 | plugin_stripheader_la_SOURCES = plugin_stripheader.c 113 | plugin_stripheader_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 114 | # 115 | plugin_siptrunk_la_SOURCES = plugin_siptrunk.c 116 | plugin_siptrunk_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 117 | # 118 | plugin_fix_fbox_anoncall_la_SOURCES = plugin_fix_fbox_anoncall.c 119 | plugin_fix_fbox_anoncall_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 120 | # 121 | plugin_stats_la_SOURCES = plugin_stats.c 122 | plugin_stats_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 123 | # 124 | plugin_blacklist_la_SOURCES = plugin_blacklist.c 125 | plugin_blacklist_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -shrext '.so' 126 | plugin_blacklist_la_LIBADD = -lsqlite3 127 | 128 | # 129 | # Siproxd itself 130 | # (references DLOPENPLUGINS defined above - must be placed afterwards 131 | # else Cygwin goes beserk when building...) 132 | # 133 | sbin_PROGRAMS = siproxd 134 | siproxd_LDFLAGS = -export-dynamic 135 | #&&&siproxd_LDADD = $(LIBLTDL) $(DLOPENPLUGINS) 136 | siproxd_LDADD = $(LIBLTDL) 137 | siproxd_SOURCES = siproxd.c proxy.c register.c sock.c utils.c \ 138 | sip_utils.c sip_layer.c log.c readconf.c rtpproxy.c \ 139 | rtpproxy_relay.c accessctl.c route_processing.c \ 140 | security.c auth.c fwapi.c resolve.c \ 141 | dejitter.c plugins.c redirect_cache.c 142 | 143 | 144 | # 145 | # an example for a custom firewall control module 146 | # that can be linked into siproxd (--with-custom-fwmodule) 147 | # 148 | noinst_LIBRARIES = libcustom_fw_module.a 149 | libcustom_fw_module_a_SOURCES = custom_fw_module.c 150 | 151 | 152 | noinst_HEADERS = log.h siproxd.h digcalc.h rtpproxy.h \ 153 | fwapi.h plugins.h dejitter.h \ 154 | redirect_cache.h 155 | 156 | EXTRA_DIST = .buildno 157 | 158 | # 159 | # count BUILDs - each time increment by one and define the 160 | # C macro BUILDNO. bind it to a file everybody includes (log.h) 161 | # 162 | log.h: increment_build 163 | 164 | increment_build: 165 | @echo "incrementing BUILD number" 166 | @if [ -f .buildno ]; then \ 167 | bld=`cat .buildno`; \ 168 | bld=`expr $${bld} + 1`; \ 169 | else \ 170 | bld=1; \ 171 | fi; \ 172 | echo "$${bld}" >.buildno; 173 | -------------------------------------------------------------------------------- /src/accessctl.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002-2008 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | #include "siproxd.h" 32 | #include "log.h" 33 | 34 | /* configuration storage */ 35 | extern struct siproxd_config configuration; 36 | 37 | 38 | /* 39 | * verifies the from address agains the access lists 40 | * defined in the configuration file. 41 | * 42 | * returns a bitmask with ACCESSCTL_SIP, ACCESSCTL_REG 43 | */ 44 | int accesslist_check (struct sockaddr_in from) { 45 | int access = 0; 46 | 47 | DEBUGC(DBCLASS_ACCESS,"deny list (SIP):%s", 48 | configuration.hosts_deny_sip? configuration.hosts_deny_sip : "*NULL*"); 49 | DEBUGC(DBCLASS_ACCESS,"allow list (SIP):%s", 50 | configuration.hosts_allow_sip? configuration.hosts_allow_sip : "*NULL*"); 51 | DEBUGC(DBCLASS_ACCESS,"allow list (REG):%s", 52 | configuration.hosts_allow_reg? configuration.hosts_allow_reg : "*NULL*"); 53 | 54 | /* 55 | * check DENY list 56 | */ 57 | if ( (configuration.hosts_deny_sip !=NULL) && 58 | (strcmp(configuration.hosts_deny_sip,"")!=0) ) { 59 | /* non-empty list -> check agains it */ 60 | if (process_aclist(configuration.hosts_deny_sip, from)== STS_SUCCESS) { 61 | /* yup - this one is blacklisted */ 62 | DEBUGC(DBCLASS_ACCESS,"caught by deny list"); 63 | return 0; 64 | } 65 | } 66 | 67 | /* 68 | * check SIP allow list 69 | */ 70 | if ( (configuration.hosts_allow_sip !=NULL) && 71 | (strcmp(configuration.hosts_allow_sip,"")!=0) ) { 72 | /* non-empty list -> check agains it */ 73 | if (process_aclist(configuration.hosts_allow_sip, from)==STS_SUCCESS) { 74 | /* SIP access granted */ 75 | DEBUGC(DBCLASS_ACCESS,"granted SIP access"); 76 | access |= ACCESSCTL_SIP; 77 | } 78 | } else { 79 | access |= ACCESSCTL_SIP; 80 | } 81 | 82 | /* 83 | * check SIP registration allow list 84 | */ 85 | if ( (configuration.hosts_allow_reg !=NULL) && 86 | (strcmp(configuration.hosts_allow_reg,"")!=0) ) { 87 | /* non-empty list -> check against it */ 88 | if (process_aclist(configuration.hosts_allow_reg, from)==STS_SUCCESS) { 89 | /* SIP registration access granted */ 90 | DEBUGC(DBCLASS_ACCESS,"granted REG/SIP access"); 91 | access |= ACCESSCTL_REG | ACCESSCTL_SIP; 92 | } 93 | } else { 94 | access |= ACCESSCTL_REG; 95 | } 96 | 97 | DEBUGC(DBCLASS_ACCESS,"access check =%i", access); 98 | return access; 99 | } 100 | 101 | 102 | /* 103 | * checks for a match of the 'from' address with the supplied 104 | * access list. 105 | * 106 | * RETURNS 107 | * STS_SUCCESS for a match 108 | * STS_FAILURE for no match 109 | */ 110 | int process_aclist (char *aclist, struct sockaddr_in from) { 111 | int i, sts; 112 | int lastentry; 113 | char *p1, *p2; 114 | char address[HOSTNAME_SIZE+1]; /* dotted decimal IP - max 15 chars */ 115 | /* or hostname*/ 116 | char mask[8]; /* mask - max 2 digits */ 117 | int mask_int; 118 | struct in_addr inaddr; 119 | unsigned int bitmask; 120 | 121 | 122 | for (i=0, p1=aclist, lastentry=0; !lastentry && p1-aclist= sizeof(address)) { 135 | ERROR("CONFIG: accesslist [%s]- illegal ip address format or netmask separator", aclist); 136 | return STS_FAILURE; 137 | } 138 | memset(address,0,sizeof(address)); 139 | memcpy(address,p1,p2-p1); 140 | p1=p2+1; 141 | 142 | /* mask */ 143 | p2=strchr(p1,','); 144 | if (!p2) { /* then this must be the last entry in the list */ 145 | p2=strchr(p1,'\0'); 146 | lastentry=1; 147 | } 148 | 149 | if (p2-p1 >= sizeof(mask)) { 150 | ERROR("CONFIG: accesslist [%s]- illegal netmask format or IP separator", aclist); 151 | return STS_FAILURE; 152 | } 153 | memset(mask,0,sizeof(mask)); 154 | memcpy(mask,p1,p2-p1); 155 | p1=p2+1; 156 | 157 | DEBUGC(DBCLASS_ACCESS,"[%i] extracted address=%s", i, address); 158 | DEBUGC(DBCLASS_ACCESS,"[%i] extracted mask =%s", i, mask); 159 | 160 | /* 161 | * check for a match 162 | */ 163 | sts=get_ip_by_host(address, &inaddr); 164 | if (sts == STS_FAILURE) { 165 | DEBUGC(DBCLASS_ACCESS, "process_aclist: cannot resolve address [%s]", 166 | address); 167 | return STS_FAILURE; 168 | } 169 | 170 | mask_int=atoi(mask); 171 | if ((mask_int < 0) || (mask_int > 32)) mask_int=32; 172 | bitmask= (mask_int)? (0xffffffff<<(32-mask_int)) : 0; 173 | 174 | DEBUGC(DBCLASS_ACCESS,"check match: entry=%i, filter=%lx, from=%lx", i, 175 | (long)ntohl(inaddr.s_addr) & bitmask, 176 | (long)ntohl(from.sin_addr.s_addr) & bitmask); 177 | 178 | if ( (ntohl(inaddr.s_addr) & bitmask) == 179 | (ntohl(from.sin_addr.s_addr) & bitmask) ) { 180 | DEBUGC(DBCLASS_ACCESS, "process_aclist: MATCH"); 181 | return STS_SUCCESS; 182 | } 183 | } 184 | 185 | DEBUGC(DBCLASS_ACCESS, "process_aclist: no match"); 186 | return STS_FAILURE; 187 | } 188 | -------------------------------------------------------------------------------- /src/custom_fw_module.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2004-2008 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | /* 22 | * This is just an example of how to build your custom 23 | * interface between siproxd and your firewall. 24 | * 25 | * Take this as a starting point for your own code. 26 | * 27 | * To build siproxd with you own firewall control module: 28 | * 1) compile your interface module (e.g. this example code) 29 | * and make an static library out of it. 30 | * 2) configure siproxd with: 31 | * ./configure --with-custom-fwmodule=/.a 32 | * (for example: --with-custom-fwmodule=`pwd`/src/libcustom_fw_module.a) 33 | * 34 | * 35 | * The START_RTP action will be called BEFORE the RTP stream 36 | * actually is started. The STOP_RTP action will be called after 37 | * the RTP stream has been stopped. 38 | * START_RTP will only be called once for an starting RTP stream, 39 | * in case of repetitions (SIP INVITE sequence) it will not 40 | * be called multiple times. 41 | * 42 | * The code here is called synchroneously, means the time you spend 43 | * in here doing things, siproxd will not do anything else, so 44 | * try to do thins as fast as possible and don't wait for something 45 | * to happen. 46 | * 47 | */ 48 | 49 | #include /* sprintf */ 50 | #include /* strcat */ 51 | 52 | 53 | #include 54 | #include 55 | #include "fwapi.h" 56 | #include "log.h" 57 | 58 | /* 59 | * some prototypes of util.c - so I don't have to suck in the 60 | * whole bunch of include files. You probably will not use this 61 | * in your code anyway - or then should make it in a proper way. 62 | */ 63 | char *utils_inet_ntoa(struct in_addr in); 64 | 65 | /* 66 | * Should return with 0 on success. 67 | * If return status is != 0, siproxd will complain with an 68 | * an ERROR() but continue. 69 | */ 70 | int custom_fw_control(fw_ctl_t fwdata) { 71 | static char tmp[256]; 72 | 73 | tmp[0]='\0'; 74 | switch (fwdata.action) { 75 | case ACT_START_RTP: 76 | strcat(tmp, "ACT_START_RTP: "); 77 | break; 78 | case ACT_STOP_RTP: 79 | strcat(tmp, "ACT_STOP_RTP: "); 80 | break; 81 | default: 82 | strcat(tmp, "ACT_unknown: "); 83 | break; 84 | } 85 | 86 | switch (fwdata.direction) { 87 | case DIR_IN: 88 | strcat(tmp, "DIR_IN "); 89 | break; 90 | case DIR_OUT: 91 | strcat(tmp, "DIR_OUT "); 92 | break; 93 | default: 94 | strcat(tmp, "DIR_unknown "); 95 | break; 96 | } 97 | 98 | sprintf(&tmp[strlen(tmp)],"[lcl %s:%i] ", 99 | utils_inet_ntoa(fwdata.local_ipaddr), 100 | fwdata.local_port); 101 | 102 | sprintf(&tmp[strlen(tmp)],"[rem %s:%i] ", 103 | utils_inet_ntoa(fwdata.remote_ipaddr), 104 | fwdata.remote_port); 105 | 106 | INFO("CUSTOM: %s", tmp); 107 | 108 | return 0; 109 | } 110 | -------------------------------------------------------------------------------- /src/dejitter.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006-2008 Hans Carlos Hofmann , 3 | Thomas Ries 4 | 5 | This file is part of Siproxd. 6 | 7 | Siproxd is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License, or 10 | (at your option) any later version. 11 | 12 | Siproxd is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warrantry of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Siproxd; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifdef GPL 23 | #define USE_DEJITTER 24 | 25 | typedef struct { 26 | void *next; /* next free or next que element */ 27 | int socked; /* socket number */ 28 | size_t message_len; /* length of message */ 29 | int flags; /* flags */ 30 | struct sockaddr_in dst_addr; /* where shall i send */ 31 | struct timeval transm_time; /* when shall i send */ 32 | rtp_proxytable_t *errret; /* deliver error status */ 33 | rtp_buff_t rtp_buff; /* Data storage */ 34 | } rtp_delayed_message; 35 | 36 | 37 | /* dejitter */ 38 | void dejitter_init(void); 39 | void dejitter_delayedsendto(int s, const void *msg, size_t len, int flags, 40 | const struct sockaddr_in *to, 41 | const struct timeval *tv, 42 | const struct timeval *current_tv, 43 | rtp_proxytable_t *errret, int nolock); 44 | void dejitter_cancel(rtp_proxytable_t *dropentry); 45 | void dejitter_flush(struct timeval *current_tv, int nolock); 46 | int dejitter_delay_of_next_tx(struct timeval *tv, struct timeval *current_tv); 47 | void dejitter_init_time(timecontrol_t *tc, int dejitter); 48 | void dejitter_calc_tx_time(rtp_buff_t *rtp_buff, timecontrol_t *tc, 49 | struct timeval *input_tv, 50 | struct timeval *ttv); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /src/digcalc.h: -------------------------------------------------------------------------------- 1 | 2 | /* TAKEN from rcf2617.txt */ 3 | 4 | /* $Id$ */ 5 | 6 | #ifndef _DIGCALC_H_ 7 | #define _DIGCALC_H_ 8 | 9 | #define HASHLEN 16 10 | typedef unsigned char HASH[HASHLEN]; 11 | #define HASHHEXLEN 32 12 | typedef unsigned char HASHHEX[HASHHEXLEN+1]; 13 | #define IN 14 | #define OUT 15 | 16 | /* calculate H(A1) as per HTTP Digest spec */ 17 | void DigestCalcHA1( 18 | IN char * pszAlg, 19 | IN char * pszUserName, 20 | IN char * pszRealm, 21 | IN char * pszPassword, 22 | IN char * pszNonce, 23 | IN char * pszCNonce, 24 | OUT HASHHEX SessionKey 25 | ); 26 | 27 | /* calculate request-digest/response-digest as per HTTP Digest spec */ 28 | void DigestCalcResponse( 29 | IN HASHHEX HA1, /* H(A1) */ 30 | IN char * pszNonce, /* nonce from server */ 31 | IN char * pszNonceCount, /* 8 hex digits */ 32 | IN char * pszCNonce, /* client nonce */ 33 | IN char * pszQop, /* qop-value: "", "auth", "auth-int" */ 34 | IN char * pszMethod, /* method from the request */ 35 | IN char * pszDigestUri, /* requested URL */ 36 | IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */ 37 | OUT HASHHEX Response /* request-digest or response-digest */ 38 | ); 39 | 40 | 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/fwapi.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2004-2008 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include "siproxd.h" 25 | #include "fwapi.h" 26 | #include "log.h" 27 | 28 | int fwapi_start_rtp(int rtp_direction, 29 | struct in_addr local_ipaddr, int local_port, 30 | struct in_addr remote_ipaddr, int remote_port) { 31 | #ifdef CUSTOM_FWMODULE 32 | int sts; 33 | fw_ctl_t fwdata; 34 | fwdata.action = ACT_START_RTP; 35 | fwdata.direction = (rtp_direction == DIR_INCOMING)? DIR_IN: DIR_OUT; 36 | memcpy(&fwdata.local_ipaddr, &local_ipaddr, sizeof(fwdata.local_ipaddr)); 37 | fwdata.local_port = local_port; 38 | memcpy(&fwdata.remote_ipaddr, &remote_ipaddr, sizeof(fwdata.remote_ipaddr)); 39 | fwdata.remote_port = remote_port; 40 | 41 | sts=custom_fw_control(fwdata); 42 | if (sts != STS_SUCCESS) { 43 | ERROR("Custom firewall module returned error [START, sts=%i]",sts); 44 | } 45 | #endif 46 | return STS_SUCCESS; 47 | } 48 | 49 | int fwapi_stop_rtp(int rtp_direction, 50 | struct in_addr local_ipaddr, int local_port, 51 | struct in_addr remote_ipaddr, int remote_port) { 52 | #ifdef CUSTOM_FWMODULE 53 | int sts; 54 | fw_ctl_t fwdata; 55 | fwdata.action = ACT_STOP_RTP; 56 | fwdata.direction = (rtp_direction == DIR_INCOMING)? DIR_IN: DIR_OUT; 57 | memcpy(&fwdata.local_ipaddr, &local_ipaddr, sizeof(fwdata.local_ipaddr)); 58 | fwdata.local_port = local_port; 59 | memcpy(&fwdata.remote_ipaddr, &remote_ipaddr, sizeof(fwdata.remote_ipaddr)); 60 | fwdata.remote_port = remote_port; 61 | 62 | sts=custom_fw_control(fwdata); 63 | if (sts != STS_SUCCESS) { 64 | ERROR("Custom firewall module returned error [STOP, sts=%i]",sts); 65 | } 66 | #endif 67 | return STS_SUCCESS; 68 | } 69 | -------------------------------------------------------------------------------- /src/fwapi.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2004-2008 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | 22 | /* $Id$ */ 23 | 24 | /* 25 | * constants 26 | */ 27 | #define ACT_START_RTP 1 /* action: start RTP stream */ 28 | #define ACT_STOP_RTP 2 /* action: stop RTP stream */ 29 | 30 | #define DIR_IN 1 /* direction: incoming */ 31 | #define DIR_OUT 2 /* direction: outgoing */ 32 | 33 | 34 | /* 35 | * structure passed to custom firewall control module 36 | */ 37 | typedef struct { 38 | int action; 39 | int direction; 40 | 41 | struct in_addr local_ipaddr; 42 | int local_port; 43 | 44 | struct in_addr remote_ipaddr; 45 | int remote_port; 46 | 47 | } fw_ctl_t; 48 | 49 | 50 | /* 51 | * Functions that must be present in custom firewall control module. 52 | * Siproxd will link against it. 53 | */ 54 | int custom_fw_control(fw_ctl_t fwdata); 55 | 56 | -------------------------------------------------------------------------------- /src/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002-2008 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | /* $Id$ */ 22 | 23 | #include 24 | 25 | #define DBCLASS_BABBLE 0x00000001 /* babble (like entering/leaving fnc)*/ 26 | #define DBCLASS_NET 0x00000002 /* network */ 27 | #define DBCLASS_SIP 0x00000004 /* SIP manipulations */ 28 | #define DBCLASS_REG 0x00000008 /* Client registration */ 29 | #define DBCLASS_NOSPEC 0x00000010 /* non specified class */ 30 | #define DBCLASS_PROXY 0x00000020 /* proxy */ 31 | #define DBCLASS_DNS 0x00000040 /* DNS stuff */ 32 | #define DBCLASS_NETTRAF 0x00000080 /* network traffic */ 33 | #define DBCLASS_CONFIG 0x00000100 /* configuration */ 34 | #define DBCLASS_RTP 0x00000200 /* RTP proxy */ 35 | #define DBCLASS_ACCESS 0x00000400 /* Access list evaluation */ 36 | #define DBCLASS_AUTH 0x00000800 /* Authentication */ 37 | #define DBCLASS_PLUGIN 0x00001000 /* Plugins */ 38 | #define DBCLASS_RTPBABL 0x00002000 /* RTP babble */ 39 | #define DBCLASS_ALL 0xffffffff /* All classes */ 40 | 41 | void log_init(void); 42 | void log_end(void); 43 | 44 | void log_set_pattern(unsigned int pattern); 45 | unsigned int log_get_pattern(void); 46 | void log_set_stderr(int tostdout); 47 | void log_set_silence(int level); 48 | void log_set_listen_port(int port); 49 | void log_tcp_listen(void); 50 | void log_tcp_connect(void); 51 | 52 | #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) 53 | # define GNUC_PRINTF(format_idx, arg_idx) \ 54 | __attribute__((__format__ (__printf__, format_idx, arg_idx))) 55 | #else 56 | # define GNUC_PRINTF(format_idx, arg_idx) 57 | #endif 58 | 59 | #undef DEBUG 60 | #define DEBUG(F...) log_debug(1,__FILE__, __LINE__,F) 61 | 62 | #define DEBUGC(C,F...) log_debug(C,__FILE__, __LINE__,F) 63 | void log_debug(unsigned int class, char *file, int line, const char *format, ...) GNUC_PRINTF(4, 5); 64 | 65 | #define ERROR(F...) log_error(__FILE__, __LINE__,F) 66 | void log_error(char *file, int line, const char *format, ...) GNUC_PRINTF(3, 4); 67 | 68 | #define WARN(F...) log_warn(__FILE__, __LINE__,F) 69 | void log_warn(char *file, int line, const char *format, ...) GNUC_PRINTF(3, 4); 70 | 71 | #define INFO(F...) log_info(__FILE__, __LINE__,F) 72 | void log_info(char *file, int line, const char *format, ...) GNUC_PRINTF(3, 4); 73 | 74 | /* tobedone: dump a buffer */ 75 | #define DUMP_BUFFER(C,F,L) log_dump_buffer(C,__FILE__, __LINE__,F,L) 76 | void log_dump_buffer(unsigned int class, char *file, int line, 77 | char *buffer, int length); 78 | -------------------------------------------------------------------------------- /src/plugin_defaulttarget.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2008 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warrantry of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | /* must be defined before including */ 22 | #define PLUGIN_NAME plugin_defaulttarget 23 | 24 | #include "config.h" 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #include "siproxd.h" 35 | #include "plugins.h" 36 | #include "log.h" 37 | 38 | /* Plug-in identification */ 39 | static char name[]="plugin_defaulttarget"; 40 | static char desc[]="Forwards all unknown calls to a default internal location"; 41 | 42 | /* global configuration storage - required for config file location */ 43 | extern struct siproxd_config configuration; 44 | 45 | /* plugin configuration storage */ 46 | static struct plugin_config { 47 | char *target; 48 | int log; 49 | } plugin_cfg; 50 | 51 | /* Instructions for config parser */ 52 | static cfgopts_t plugin_cfg_opts[] = { 53 | { "plugin_defaulttarget_target", TYP_STRING, &plugin_cfg.target, {0, NULL} }, 54 | { "plugin_defaulttarget_log", TYP_INT4, &plugin_cfg.log, {0, NULL} }, 55 | {0, 0, 0} 56 | }; 57 | /* local storage */ 58 | static osip_contact_t *default_target = NULL; 59 | 60 | 61 | /* local prototypes */ 62 | static int plugin_defaulttarget_redirect(sip_ticket_t *ticket); 63 | 64 | 65 | /* 66 | * Initialization. 67 | * Called once suring siproxd startup. 68 | */ 69 | int PLUGIN_INIT(plugin_def_t *plugin_def) { 70 | 71 | /* API version number of siproxd that this plugin is built against. 72 | * This constant will change whenever changes to the API are made 73 | * that require adaptions in the plugin. */ 74 | plugin_def->api_version=SIPROXD_API_VERSION; 75 | 76 | /* Name and descriptive text of the plugin */ 77 | plugin_def->name=name; 78 | plugin_def->desc=desc; 79 | 80 | /* Execution mask - during what stages of SIP processing shall 81 | * the plugin be called. */ 82 | plugin_def->exe_mask=PLUGIN_DETERMINE_TARGET; 83 | 84 | /* read the config file */ 85 | if (read_config(configuration.configfile, 86 | configuration.config_search, 87 | plugin_cfg_opts, name) == STS_FAILURE) { 88 | ERROR("Plugin '%s': could not load config file", name); 89 | return STS_FAILURE; 90 | } 91 | 92 | /* parse the default target URI testwise */ 93 | osip_contact_init(&default_target); 94 | if (osip_contact_parse(default_target, plugin_cfg.target) != 0) { 95 | /* parsing failed, so the config file must contain CRAP */ 96 | ERROR("%s: Illegal default target [%s] - cannot parse!", 97 | name, plugin_cfg.target); 98 | return STS_FAILURE; 99 | } 100 | 101 | 102 | return STS_SUCCESS; 103 | } 104 | 105 | /* 106 | * Processing. 107 | * 108 | */ 109 | int PLUGIN_PROCESS(int stage, sip_ticket_t *ticket){ 110 | /* stage contains the PLUGIN_* value - the stage of SIP processing. */ 111 | int sts; 112 | 113 | sts = STS_SUCCESS; 114 | sip_find_direction(ticket, NULL); 115 | 116 | /* direction is unknown and SIP message is a REQUEST */ 117 | if ((ticket->direction == DIRTYP_UNKNOWN) && 118 | (MSG_IS_REQUEST(ticket->sipmsg)) && 119 | (MSG_IS_INVITE(ticket->sipmsg))) { 120 | 121 | /* LOG if master wishes so */ 122 | if (plugin_cfg.log) { 123 | osip_uri_t *to_url=ticket->sipmsg->to->url; 124 | osip_uri_t *from_url=ticket->sipmsg->from->url; 125 | INFO("Unknown Target [rcvd IP=%s:%u], From: %s@%s, redirecting To: %s@%s -> %s", 126 | utils_inet_ntoa(ticket->from.sin_addr),ntohs(ticket->from.sin_port), 127 | from_url->username? from_url->username:"*NULL*", 128 | from_url->host? from_url->host: "*NULL*", 129 | to_url->username? to_url->username:"*NULL*", 130 | to_url->host? to_url->host: "*NULL*", 131 | plugin_cfg.target); 132 | } 133 | 134 | /* target defined in config file */ 135 | if (plugin_cfg.target) { 136 | /* reply with a "302 Moved temporarily" back to the sender */ 137 | sts = plugin_defaulttarget_redirect(ticket); 138 | } 139 | return sts; 140 | } 141 | 142 | /* Catch the ACK following the redirect */ 143 | if ((ticket->direction == DIRTYP_UNKNOWN) && 144 | (MSG_IS_REQUEST(ticket->sipmsg)) && 145 | (MSG_IS_ACK(ticket->sipmsg))) { 146 | /* eat it up and don't react */ 147 | return STS_SIP_SENT; 148 | } 149 | return STS_SUCCESS; 150 | } 151 | 152 | /* 153 | * De-Initialization. 154 | * Called during shutdown of siproxd. Gives the plugin the chance 155 | * to clean up its mess (e.g. dynamic memory allocation, database 156 | * connections, whatever the plugin messes around with) 157 | */ 158 | int PLUGIN_END(plugin_def_t *plugin_def){ 159 | return STS_SUCCESS; 160 | } 161 | 162 | 163 | /*--------------------------------------------------------------------*/ 164 | /* private plugin code */ 165 | static int plugin_defaulttarget_redirect(sip_ticket_t *ticket) { 166 | int i; 167 | osip_contact_t *contact = NULL; 168 | 169 | /* remove all Contact headers in message */ 170 | for (i=0; (contact != NULL) || (i == 0); i++) { 171 | osip_message_get_contact(ticket->sipmsg, 0, &contact); 172 | if (contact) { 173 | osip_list_remove(&(ticket->sipmsg->contacts),0); 174 | osip_contact_free(contact); 175 | } 176 | } /* for i */ 177 | 178 | /* use a "302 Moved temporarily" response back to the client */ 179 | /* new target is within the Contact Header */ 180 | 181 | /* Clone the target contact header we initialized during plugin load */ 182 | osip_contact_init(&contact); 183 | osip_contact_clone(default_target, &contact); 184 | 185 | osip_list_add(&(ticket->sipmsg->contacts),contact,0); 186 | 187 | /* sent redirect message back to local client */ 188 | sip_gen_response(ticket, 302 /*Moved temporarily*/); 189 | 190 | return STS_SIP_SENT; 191 | } 192 | -------------------------------------------------------------------------------- /src/plugin_demo.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2008 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warrantry of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | /* must be defined before including */ 22 | #define PLUGIN_NAME plugin_demo 23 | 24 | #include "config.h" 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #include "siproxd.h" 35 | #include "plugins.h" 36 | #include "log.h" 37 | 38 | /* Plug-in identification */ 39 | static char name[]="plugin_demo"; 40 | static char desc[]="This is just a demo plugin without any purpose"; 41 | 42 | /* global configuration storage - required for config file location */ 43 | extern struct siproxd_config configuration; 44 | 45 | /* plugin configuration storage */ 46 | static struct plugin_config { 47 | char *string; 48 | } plugin_cfg; 49 | 50 | /* Instructions for config parser */ 51 | static cfgopts_t plugin_cfg_opts[] = { 52 | { "plugin_demo_string", TYP_STRING, &plugin_cfg.string, {0, NULL} }, 53 | {0, 0, 0} 54 | }; 55 | 56 | 57 | /* 58 | * Initialization. 59 | * Called once suring siproxd startup. 60 | */ 61 | int PLUGIN_INIT(plugin_def_t *plugin_def) { 62 | /* API version number of siproxd that this plugin is built against. 63 | * This constant will change whenever changes to the API are made 64 | * that require adaptions in the plugin. */ 65 | plugin_def->api_version=SIPROXD_API_VERSION; 66 | 67 | /* Name and descriptive text of the plugin */ 68 | plugin_def->name=name; 69 | plugin_def->desc=desc; 70 | 71 | /* Execution mask - during what stages of SIP processing shall 72 | * the plugin be called. */ 73 | plugin_def->exe_mask=PLUGIN_DETERMINE_TARGET|PLUGIN_PRE_PROXY; 74 | 75 | /* read the config file */ 76 | if (read_config(configuration.configfile, 77 | configuration.config_search, 78 | plugin_cfg_opts, name) == STS_FAILURE) { 79 | ERROR("Plugin '%s': could not load config file", name); 80 | return STS_FAILURE; 81 | } 82 | 83 | INFO("plugin_demo is initialized"); 84 | return STS_SUCCESS; 85 | } 86 | 87 | /* 88 | * Processing. 89 | * 90 | */ 91 | int PLUGIN_PROCESS(int stage, sip_ticket_t *ticket){ 92 | /* stage contains the PLUGIN_* value - the stage of SIP processing. */ 93 | INFO("plugin_demo: processing - stage %i",stage); 94 | return STS_SUCCESS; 95 | } 96 | 97 | /* 98 | * De-Initialization. 99 | * Called during shutdown of siproxd. Gives the plugin the chance 100 | * to clean up its mess (e.g. dynamic memory allocation, database 101 | * connections, whatever the plugin messes around with) 102 | */ 103 | int PLUGIN_END(plugin_def_t *plugin_def){ 104 | INFO("plugin_demo ends here"); 105 | return STS_SUCCESS; 106 | } 107 | 108 | -------------------------------------------------------------------------------- /src/plugin_fix_DTAG.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2015 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warrantry of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | /* must be defined before including */ 22 | #define PLUGIN_NAME plugin_fix_DTAG 23 | 24 | #include "config.h" 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #include "siproxd.h" 35 | #include "plugins.h" 36 | #include "log.h" 37 | 38 | /* Plug-in identification */ 39 | static char name[]="plugin_fix_DTAG"; 40 | static char desc[]="Fixes issues with DTAG (t-online.de) broken SIP headers"; 41 | 42 | /* global configuration storage - required for config file location */ 43 | extern struct siproxd_config configuration; 44 | 45 | /* plugin configuration storage */ 46 | static struct plugin_config { 47 | char *networks; 48 | } plugin_cfg; 49 | 50 | /* Instructions for config parser */ 51 | static cfgopts_t plugin_cfg_opts[] = { 52 | { "plugin_fix_DTAG_networks", TYP_STRING, &plugin_cfg.networks, {0, NULL} }, 53 | {0, 0, 0} 54 | }; 55 | 56 | /* Prototypes */ 57 | static int sip_fix_topvia(sip_ticket_t *ticket); 58 | 59 | 60 | /* 61 | * Initialization. 62 | * Called once suring siproxd startup. 63 | */ 64 | int PLUGIN_INIT(plugin_def_t *plugin_def) { 65 | /* API version number of siproxd that this plugin is built against. 66 | * This constant will change whenever changes to the API are made 67 | * that require adaptions in the plugin. */ 68 | plugin_def->api_version=SIPROXD_API_VERSION; 69 | 70 | /* Name and descriptive text of the plugin */ 71 | plugin_def->name=name; 72 | plugin_def->desc=desc; 73 | 74 | /* Execution mask - during what stages of SIP processing shall 75 | * the plugin be called. */ 76 | plugin_def->exe_mask=PLUGIN_PRE_PROXY; 77 | 78 | /* read the config file */ 79 | if (read_config(configuration.configfile, 80 | configuration.config_search, 81 | plugin_cfg_opts, name) == STS_FAILURE) { 82 | ERROR("Plugin '%s': could not load config file", name); 83 | return STS_FAILURE; 84 | } 85 | 86 | INFO("plugin_fix_DTAG is initialized"); 87 | return STS_SUCCESS; 88 | } 89 | 90 | /* 91 | * Processing. 92 | * 93 | */ 94 | int PLUGIN_PROCESS(int stage, sip_ticket_t *ticket){ 95 | /* stage contains the PLUGIN_* value - the stage of SIP processing. */ 96 | int type; 97 | osip_via_t *via; 98 | struct sockaddr_in from; 99 | 100 | type = ticket->direction; 101 | 102 | DEBUGC(DBCLASS_PLUGIN, "plugin_fix_DTAG: type=%i", type); 103 | 104 | /* Incoming SIP response? */ 105 | if (type == RESTYP_INCOMING) { 106 | /* a Via header needs to be present in response */ 107 | if((via = osip_list_get(&(ticket->sipmsg->vias), 0)) == NULL) { 108 | WARN("no Via header found in incoming SIP message"); 109 | return STS_SUCCESS; 110 | } 111 | 112 | /* check for Via IP in configured range */ 113 | DEBUGC(DBCLASS_PLUGIN, "plugin_fix_DTAG: processing VIA host [%s]", 114 | via->host); 115 | get_ip_by_host(via->host, &(from.sin_addr)); 116 | if ((plugin_cfg.networks != NULL) && 117 | (strcmp(plugin_cfg.networks, "") !=0) && 118 | (process_aclist(plugin_cfg.networks, ticket->from) == STS_SUCCESS) && 119 | (process_aclist(plugin_cfg.networks, from) == STS_SUCCESS)) { 120 | 121 | /* VIA & Sender IP are in list, fix Via header */ 122 | DEBUGC(DBCLASS_PLUGIN, "plugin_fix_DTAG: replacing a bogus via"); 123 | 124 | if (sip_fix_topvia(ticket) == STS_FAILURE) { 125 | ERROR("patching inbound Via failed!"); 126 | } 127 | } else { 128 | DEBUGC(DBCLASS_PLUGIN, "plugin_fix_DTAG: not match, returning."); 129 | } 130 | DEBUGC(DBCLASS_PLUGIN, "plugin_fix_DTAG: done"); 131 | } 132 | return STS_SUCCESS; 133 | } 134 | 135 | /* 136 | * De-Initialization. 137 | * Called during shutdown of siproxd. Gives the plugin the chance 138 | * to clean up its mess (e.g. dynamic memory allocation, database 139 | * connections, whatever the plugin messes around with) 140 | */ 141 | int PLUGIN_END(plugin_def_t *plugin_def){ 142 | INFO("plugin_fix_DTAG ends here"); 143 | return STS_SUCCESS; 144 | } 145 | 146 | /*--------------------------------------------------------------------*/ 147 | static int sip_fix_topvia(sip_ticket_t *ticket) { 148 | osip_via_t *via; 149 | int sts; 150 | 151 | if((via = osip_list_get(&(ticket->sipmsg->vias), 0)) != NULL) { 152 | /* 1) IP of Via has been checked beforehand. */ 153 | 154 | /* 2) remove broken via header */ 155 | DEBUGC(DBCLASS_PLUGIN, "plugin_fix_DTAG: removing topmost via"); 156 | sts = osip_list_remove(&(ticket->sipmsg->vias), 0); 157 | osip_via_free (via); 158 | via = NULL; 159 | 160 | /* 3) add my via header */ 161 | DEBUGC(DBCLASS_PLUGIN, "plugin_fix_DTAG: adding new via"); 162 | if (ticket->direction == RESTYP_INCOMING) { 163 | sts = sip_add_myvia(ticket, IF_OUTBOUND); 164 | if (sts == STS_FAILURE) { 165 | ERROR("adding my outbound via failed!"); 166 | } 167 | } else { 168 | sts = sip_add_myvia(ticket, IF_INBOUND); 169 | if (sts == STS_FAILURE) { 170 | ERROR("adding my inbound via failed!"); 171 | } 172 | } 173 | } 174 | 175 | return STS_SUCCESS; 176 | } 177 | 178 | -------------------------------------------------------------------------------- /src/plugin_fix_bogus_via.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2008 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warrantry of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | /* must be defined before including */ 22 | #define PLUGIN_NAME plugin_fix_bogus_via 23 | 24 | #include "config.h" 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | 35 | #include "siproxd.h" 36 | #include "plugins.h" 37 | #include "log.h" 38 | 39 | /* Plug-in identification */ 40 | static char name[]="plugin_fix_bogus_via"; 41 | static char desc[]="Fixes broken VIA headers on incoming calls"; 42 | 43 | /* global configuration storage - required for config file location */ 44 | extern struct siproxd_config configuration; 45 | 46 | /* plugin configuration storage */ 47 | static struct plugin_config { 48 | char *networks; 49 | } plugin_cfg; 50 | 51 | /* Instructions for config parser */ 52 | static cfgopts_t plugin_cfg_opts[] = { 53 | { "plugin_fix_bogus_via_networks", TYP_STRING, &plugin_cfg.networks, {0, NULL} }, 54 | {0, 0, 0} 55 | }; 56 | 57 | /* Prototypes */ 58 | static int sip_patch_topvia(sip_ticket_t *ticket); 59 | 60 | 61 | /* 62 | * Initialization. 63 | * Called once suring siproxd startup. 64 | */ 65 | int PLUGIN_INIT(plugin_def_t *plugin_def) { 66 | /* API version number of siproxd that this plugin is built against. 67 | * This constant will change whenever changes to the API are made 68 | * that require adaptions in the plugin. */ 69 | plugin_def->api_version=SIPROXD_API_VERSION; 70 | 71 | /* Name and descriptive text of the plugin */ 72 | plugin_def->name=name; 73 | plugin_def->desc=desc; 74 | 75 | /* Execution mask - during what stages of SIP processing shall 76 | * the plugin be called. */ 77 | plugin_def->exe_mask=PLUGIN_PRE_PROXY; 78 | 79 | /* read the config file */ 80 | if (read_config(configuration.configfile, 81 | configuration.config_search, 82 | plugin_cfg_opts, name) == STS_FAILURE) { 83 | ERROR("Plugin '%s': could not load config file", name); 84 | return STS_FAILURE; 85 | } 86 | 87 | INFO("plugin_fix_bogus_via is initialized"); 88 | return STS_SUCCESS; 89 | } 90 | 91 | /* 92 | * Processing. 93 | * 94 | */ 95 | int PLUGIN_PROCESS(int stage, sip_ticket_t *ticket){ 96 | /* stage contains the PLUGIN_* value - the stage of SIP processing. */ 97 | int type; 98 | osip_via_t *via; 99 | struct sockaddr_in from; 100 | 101 | type = ticket->direction; 102 | 103 | /* Incoming SIP message? */ 104 | DEBUGC(DBCLASS_PLUGIN, "plugin_fix_bogus_via: type=%i", type); 105 | if (type == REQTYP_INCOMING) { 106 | 107 | if((via = osip_list_get(&(ticket->sipmsg->vias), 0)) == NULL) { 108 | WARN("no Via header found in incoming SIP message"); 109 | return STS_SUCCESS; 110 | } 111 | 112 | get_ip_by_host(via->host, &(from.sin_addr)); 113 | 114 | /* check for Via IP in configured range */ 115 | if ((plugin_cfg.networks != NULL) && 116 | (strcmp(plugin_cfg.networks, "") !=0) && 117 | (process_aclist(plugin_cfg.networks, from) == STS_SUCCESS)) { 118 | /* is in list, patch Via header with received from IP */ 119 | DEBUGC(DBCLASS_PLUGIN, "plugin_fix_bogus_via: replacing a bogus via"); 120 | if (sip_patch_topvia(ticket) == STS_FAILURE) { 121 | ERROR("patching inbound Via failed!"); 122 | } 123 | } 124 | } 125 | return STS_SUCCESS; 126 | } 127 | 128 | /* 129 | * De-Initialization. 130 | * Called during shutdown of siproxd. Gives the plugin the chance 131 | * to clean up its mess (e.g. dynamic memory allocation, database 132 | * connections, whatever the plugin messes around with) 133 | */ 134 | int PLUGIN_END(plugin_def_t *plugin_def){ 135 | INFO("plugin_fix_bogus_via ends here"); 136 | return STS_SUCCESS; 137 | } 138 | 139 | /*--------------------------------------------------------------------*/ 140 | static int sip_patch_topvia(sip_ticket_t *ticket) { 141 | osip_via_t *via; 142 | 143 | if((via = osip_list_get(&(ticket->sipmsg->vias), 0)) != NULL) { 144 | /* clone Via header */ 145 | 146 | /* set new IP (from IP) */ 147 | osip_free(via->host); 148 | via->host=osip_malloc(IPSTRING_SIZE); 149 | snprintf(via->host, IPSTRING_SIZE, "%s", 150 | utils_inet_ntoa(ticket->from.sin_addr)); 151 | via->host[IPSTRING_SIZE-1] ='\0'; 152 | 153 | /* set new port number */ 154 | osip_free(via->port); 155 | via->port=osip_malloc(PORTSTRING_SIZE); /* 5 digits + \0 */ 156 | snprintf(via->port, PORTSTRING_SIZE, "%u", ntohs(ticket->from.sin_port)); 157 | via->port[IPSTRING_SIZE-1] ='\0'; 158 | 159 | DEBUGC(DBCLASS_PLUGIN, "plugin_fix_bogus_via: -> %s:%s", 160 | via->host, via->port); 161 | 162 | } 163 | 164 | return STS_SUCCESS; 165 | } 166 | 167 | -------------------------------------------------------------------------------- /src/plugin_logcall.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2008 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warrantry of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | /* must be defined before including */ 22 | #define PLUGIN_NAME plugin_logcall 23 | 24 | #include "config.h" 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #include "siproxd.h" 35 | #include "plugins.h" 36 | #include "log.h" 37 | 38 | /* Plug-in identification */ 39 | static char name[]="plugin_logcall"; 40 | static char desc[]="Logs calls to syslog"; 41 | 42 | /* global configuration storage - required for config file location */ 43 | extern struct siproxd_config configuration; 44 | 45 | 46 | /* 47 | * Initialization. 48 | * Called once suring siproxd startup. 49 | */ 50 | int PLUGIN_INIT(plugin_def_t *plugin_def) { 51 | /* API version number of siproxd that this plugin is built against. 52 | * This constant will change whenever changes to the API are made 53 | * that require adaptions in the plugin. */ 54 | plugin_def->api_version=SIPROXD_API_VERSION; 55 | 56 | /* Name and descriptive text of the plugin */ 57 | plugin_def->name=name; 58 | plugin_def->desc=desc; 59 | 60 | /* Execution mask - during what stages of SIP processing shall 61 | * the plugin be called. */ 62 | plugin_def->exe_mask=PLUGIN_PRE_PROXY; 63 | 64 | return STS_SUCCESS; 65 | } 66 | 67 | /* 68 | * Processing. 69 | * 70 | */ 71 | int PLUGIN_PROCESS(int stage, sip_ticket_t *ticket){ 72 | osip_message_t *request; 73 | osip_uri_t *from_url = NULL; 74 | osip_uri_t *to_url = NULL; 75 | osip_uri_t *req_uri = NULL; 76 | char *to_username =NULL; 77 | char *to_host = NULL; 78 | char *from_username =NULL; 79 | char *from_host = NULL; 80 | char *call_type = NULL; 81 | osip_call_id_t *call_id=NULL; 82 | 83 | request=ticket->sipmsg; 84 | req_uri = request->req_uri; 85 | 86 | /* From: 1st preference is From header, then try contact header */ 87 | if (request->from->url) { 88 | from_url = request->from->url; 89 | } else { 90 | from_url = (osip_uri_t *)osip_list_get(&(request->contacts), 0); 91 | } 92 | 93 | to_url = request->to->url; 94 | 95 | if (to_url) { 96 | to_username = to_url->username; 97 | to_host = to_url->host; 98 | } 99 | 100 | if (from_url) { 101 | from_username = from_url->username; 102 | from_host = from_url->host; 103 | } 104 | 105 | /* INVITE */ 106 | if (MSG_IS_INVITE(request)) { 107 | if (ticket->direction==REQTYP_INCOMING) call_type="Incoming (INVITE)"; 108 | else call_type="Outgoing (INVITE)"; 109 | /* BYE / CANCEL */ 110 | } else if (MSG_IS_ACK(request)) { 111 | call_type="Acknowledging (ACK)"; 112 | } else if (MSG_IS_BYE(request)) { 113 | call_type="Ending (BYE)"; 114 | } else if (MSG_IS_CANCEL(request)) { 115 | call_type="Ending (CANCEL)"; 116 | } 117 | 118 | /* Call-ID */ 119 | call_id = osip_message_get_call_id(request); 120 | 121 | if (call_type) { 122 | INFO("%s Call: %s@%s -> %s@%s [Req: %s@%s] [IP: %s:%u] [CID: %s@%s]", 123 | call_type, 124 | from_username ? from_username: "*NULL*", 125 | from_host ? from_host : "*NULL*", 126 | to_username ? to_username : "*NULL*", 127 | to_host ? to_host : "*NULL*", 128 | (req_uri && req_uri->username) ? req_uri->username : "*NULL*", 129 | (req_uri && req_uri->host) ? req_uri->host : "*NULL*", 130 | utils_inet_ntoa(ticket->from.sin_addr),ntohs(ticket->from.sin_port), 131 | (call_id && call_id->number) ? call_id->number : "*NULL*", 132 | (call_id && call_id->host) ? call_id->host : "*NULL*" 133 | ); 134 | } 135 | 136 | return STS_SUCCESS; 137 | } 138 | 139 | /* 140 | * De-Initialization. 141 | * Called during shutdown of siproxd. Gives the plugin the chance 142 | * to clean up its mess (e.g. dynamic memory allocation, database 143 | * connections, whatever the plugin messes around with) 144 | */ 145 | int PLUGIN_END(plugin_def_t *plugin_def){ 146 | return STS_SUCCESS; 147 | } 148 | 149 | -------------------------------------------------------------------------------- /src/plugin_prefix.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002-2011 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | /* 22 | * plugin_prefix is based on plugin_shortdial 23 | * 24 | * This plugin adds a configured prefix to outgoing calls. 25 | * Typical use is to add a dial-out code ('9' or '0') to 26 | * cover user experience with POTS dialing. 27 | */ 28 | 29 | 30 | /* must be defined before including */ 31 | #define PLUGIN_NAME plugin_prefix 32 | 33 | #include "config.h" 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | #include 45 | 46 | #include "siproxd.h" 47 | #include "plugins.h" 48 | #include "redirect_cache.h" 49 | #include "log.h" 50 | 51 | /* Plug-in identification */ 52 | static char name[]="plugin_prefix"; 53 | static char desc[]="Adds a dial-prefix as defined in config file"; 54 | 55 | /* constants */ 56 | #define REDIRECTED_TAG "redirected" 57 | #define REDIRECTED_VAL "prefix" 58 | 59 | /* global configuration storage - required for config file location */ 60 | extern struct siproxd_config configuration; 61 | 62 | 63 | /* plugin configuration storage */ 64 | static struct plugin_config { 65 | char *prefix_akey; 66 | } plugin_cfg; 67 | 68 | /* Instructions for config parser */ 69 | static cfgopts_t plugin_cfg_opts[] = { 70 | { "plugin_prefix_akey", TYP_STRING, &plugin_cfg.prefix_akey, {0, NULL} }, 71 | {0, 0, 0} 72 | }; 73 | 74 | 75 | /* local storage needed by plugin */ 76 | /* Redirect Cache: Queue Head is static */ 77 | static redirected_cache_element_t redirected_cache; 78 | 79 | 80 | /* local prototypes */ 81 | static int plugin_prefix_redirect(sip_ticket_t *ticket); 82 | static int plugin_prefix(sip_ticket_t *ticket); 83 | 84 | /* 85 | * Plugin API functions code 86 | */ 87 | /* Initialization */ 88 | int PLUGIN_INIT(plugin_def_t *plugin_def) { 89 | plugin_def->api_version=SIPROXD_API_VERSION; 90 | plugin_def->name=name; 91 | plugin_def->desc=desc; 92 | plugin_def->exe_mask=PLUGIN_DETERMINE_TARGET; 93 | 94 | /* read the config file */ 95 | if (read_config(configuration.configfile, 96 | configuration.config_search, 97 | plugin_cfg_opts, name) == STS_FAILURE) { 98 | ERROR("Plugin '%s': could not load config file", name); 99 | return STS_FAILURE; 100 | } 101 | 102 | return STS_SUCCESS; 103 | } 104 | 105 | /* Processing */ 106 | int PLUGIN_PROCESS(int stage, sip_ticket_t *ticket){ 107 | int sts; 108 | sts=plugin_prefix(ticket); 109 | return sts; 110 | } 111 | 112 | /* De-Initialization */ 113 | int PLUGIN_END(plugin_def_t *plugin_def){ 114 | return STS_SUCCESS; 115 | } 116 | 117 | 118 | /* 119 | * Workload code 120 | */ 121 | 122 | /* returns STS_SIP_SENT if processing is to be terminated, 123 | * otherwise STS_SUCCESS (go on with processing) */ 124 | /* code (entry point) */ 125 | static int plugin_prefix(sip_ticket_t *ticket) { 126 | int sts=STS_SUCCESS; 127 | osip_uri_t *req_url; 128 | osip_uri_t *to_url; 129 | osip_generic_param_t *r=NULL; 130 | 131 | /* plugin loaded and not configured, return with success */ 132 | if (plugin_cfg.prefix_akey == NULL) return STS_SUCCESS; 133 | 134 | DEBUGC(DBCLASS_PLUGIN,"plugin entered"); 135 | req_url=osip_message_get_uri(ticket->sipmsg); 136 | to_url=osip_to_get_url(ticket->sipmsg); 137 | 138 | /* only outgoing direction is handled */ 139 | sip_find_direction(ticket, NULL); 140 | if (ticket->direction != DIR_OUTGOING) 141 | return STS_SUCCESS; 142 | 143 | /* only INVITE and ACK are handled */ 144 | if (!MSG_IS_INVITE(ticket->sipmsg) && !MSG_IS_ACK(ticket->sipmsg)) 145 | return STS_SUCCESS; 146 | 147 | /* expire old cache entries */ 148 | expire_redirected_cache(&redirected_cache); 149 | 150 | /* REQ URI with username must exist, prefix string must exist */ 151 | if (!req_url || !req_url->username || !plugin_cfg.prefix_akey) 152 | return STS_SUCCESS; /* ignore */ 153 | 154 | /* Loop avoidance: 155 | * If this INVITE has already been redirected by a prior 302 156 | * moved response a "REDIRECTED_TAG" parameter should be present in the 157 | * URI. 158 | * Hopefully all UAs (Clients) do honor RFC3261 and copy the 159 | * *full* URI form the contact header into the new request header 160 | * upon a 3xx response. 161 | */ 162 | if (req_url) { 163 | osip_uri_param_get_byname(&(req_url->url_params), REDIRECTED_TAG, &r); 164 | if (r && r->gvalue && strcmp(r->gvalue,REDIRECTED_VAL)== 0) { 165 | DEBUGC(DBCLASS_PLUGIN,"Packet has already been redirected (ReqURI)"); 166 | return STS_SUCCESS; 167 | } 168 | } 169 | if (to_url) { 170 | osip_uri_param_get_byname(&(to_url->url_params), REDIRECTED_TAG, &r); 171 | if (r && r->gvalue && strcmp(r->gvalue,REDIRECTED_VAL)== 0) { 172 | DEBUGC(DBCLASS_PLUGIN,"Packet has already been redirected (ToURI)"); 173 | return STS_SUCCESS; 174 | } 175 | } 176 | 177 | /* 178 | * The called number is to be prefixed 179 | */ 180 | 181 | /* outgoing INVITE request */ 182 | if (MSG_IS_INVITE(ticket->sipmsg)) { 183 | DEBUGC(DBCLASS_PLUGIN,"processing INVITE"); 184 | sts=plugin_prefix_redirect(ticket); 185 | } 186 | /* outgoing ACK request: is result of a local 3xx answer (moved...) 187 | * 188 | * Only consume that particular ACK that belongs to a sent 302 answer, 189 | * nothing else. Otherwise the ACK from the redirected call will get 190 | * consumed as well and causes the call to be aborted (timeout). 191 | * We keep a cache with Call-Ids of such "302 moved" dialogs. 192 | * Only consume such ACKs that are part of such a dialog. 193 | */ 194 | else if (MSG_IS_ACK(ticket->sipmsg)) { 195 | if (is_in_redirected_cache(&redirected_cache, ticket) == STS_TRUE) { 196 | DEBUGC(DBCLASS_PLUGIN,"processing ACK (consume it)"); 197 | sts=STS_SIP_SENT; /* eat up the ACK that was directed to myself */ 198 | } 199 | } 200 | 201 | return sts; 202 | } 203 | 204 | 205 | /* private plugin code */ 206 | static int plugin_prefix_redirect(sip_ticket_t *ticket) { 207 | osip_uri_t *to_url=ticket->sipmsg->to->url; 208 | char *to_user=to_url->username; 209 | char *new_to_user=NULL; 210 | int i; 211 | size_t username_len; 212 | osip_contact_t *contact = NULL; 213 | 214 | /* including \0 + leading character(s) */ 215 | username_len=strlen(to_user) + strlen(plugin_cfg.prefix_akey) + 1; 216 | 217 | new_to_user = osip_malloc(username_len); /* *_len excluding \0 */ 218 | if (!new_to_user) return STS_SUCCESS; 219 | 220 | /* use a "302 Moved temporarily" response back to the client */ 221 | /* new target is within the Contact Header */ 222 | 223 | /* remove all Contact headers in message */ 224 | for (i=0; (contact != NULL) || (i == 0); i++) { 225 | osip_message_get_contact(ticket->sipmsg, 0, &contact); 226 | if (contact) { 227 | osip_list_remove(&(ticket->sipmsg->contacts),0); 228 | osip_contact_free(contact); 229 | } 230 | } /* for i */ 231 | 232 | /* insert one new Contact header containing the new target address */ 233 | osip_contact_init(&contact); 234 | osip_uri_clone(to_url, &contact->url); 235 | 236 | /* 237 | * Add the 'REDIRECTED_TAG=REDIRECTED_VAL' parameter to URI. Required to figure out 238 | * if this INVITE has already been processed (redirected) and 239 | * does not need further attention by this plugin. 240 | * THIS IS REQUIRED TO AVOID A LOOP 241 | */ 242 | osip_uri_param_add(&(contact->url->url_params), osip_strdup(REDIRECTED_TAG), 243 | osip_strdup(REDIRECTED_VAL)); 244 | 245 | /* only copy the part that really belongs to the username */ 246 | snprintf(new_to_user, username_len, "%s%s", 247 | plugin_cfg.prefix_akey,to_user ); 248 | 249 | /* strncpy may not terminate - do it manually to be sure */ 250 | new_to_user[username_len-1]='\0'; 251 | osip_list_add(&(ticket->sipmsg->contacts),contact,0); 252 | 253 | INFO("redirecting %s -> %s", to_user, new_to_user); 254 | 255 | /* USER part is always present */ 256 | osip_free(contact->url->username); 257 | contact->url->username=new_to_user; 258 | 259 | /* sent redirect message back to local client */ 260 | add_to_redirected_cache(&redirected_cache, ticket); 261 | sip_gen_response(ticket, 302 /*Moved temporarily*/); 262 | 263 | return STS_SIP_SENT; 264 | } 265 | -------------------------------------------------------------------------------- /src/plugin_regex_body.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002-2024 Thomas Ries and Matthew Esper 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | /* 22 | * This plugin adds a regular expression rewrite support 23 | * for SIP targets. 24 | */ 25 | 26 | 27 | /* must be defined before including */ 28 | #define PLUGIN_NAME plugin_regex_body 29 | 30 | #include "config.h" 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | #include 42 | 43 | #include "siproxd.h" 44 | #include "plugins.h" 45 | #include "redirect_cache.h" 46 | #include "log.h" 47 | 48 | /* Plug-in identification */ 49 | static char name[]="plugin_regex_body"; 50 | static char desc[]="Use regular expressions to rewrite SIP message bodies"; 51 | 52 | /* global configuration storage - required for config file location */ 53 | extern struct siproxd_config configuration; 54 | 55 | /* constants */ 56 | #define REDIRECTED_TAG "redirected" 57 | #define REDIRECTED_VAL "regex" 58 | 59 | /* plugin configuration storage */ 60 | static struct plugin_config { 61 | stringa_t regex_body_desc; 62 | stringa_t regex_body_pattern; 63 | stringa_t regex_body_replace; 64 | } plugin_cfg; 65 | 66 | /* Instructions for config parser */ 67 | static cfgopts_t plugin_cfg_opts[] = { 68 | { "plugin_regex_body_desc", TYP_STRINGA,&plugin_cfg.regex_body_desc, {0, NULL} }, 69 | { "plugin_regex_body_pattern", TYP_STRINGA,&plugin_cfg.regex_body_pattern, {0, NULL} }, 70 | { "plugin_regex_body_replace", TYP_STRINGA,&plugin_cfg.regex_body_replace, {0, NULL} }, 71 | {0, 0, 0} 72 | }; 73 | 74 | /* local storage needed for regular expression handling */ 75 | static regex_t *re; 76 | 77 | 78 | /* local prototypes */ 79 | static int plugin_regex_body_init(void); 80 | static int plugin_regex_body_process(sip_ticket_t *ticket); 81 | static int plugin_regex_body_redirect(sip_ticket_t *ticket); 82 | static regmatch_t * rmatch (char *buf, int size, regex_t *re); 83 | static int rreplace (char *buf, int size, regex_t *re, regmatch_t pmatch[], char *rp); 84 | 85 | 86 | /* 87 | * Plugin API functions code 88 | */ 89 | /* Initialization */ 90 | int PLUGIN_INIT(plugin_def_t *plugin_def) { 91 | plugin_def->api_version=SIPROXD_API_VERSION; 92 | plugin_def->name=name; 93 | plugin_def->desc=desc; 94 | plugin_def->exe_mask=PLUGIN_DETERMINE_TARGET; 95 | 96 | /* read the config file */ 97 | if (read_config(configuration.configfile, 98 | configuration.config_search, 99 | plugin_cfg_opts, name) == STS_FAILURE) { 100 | ERROR("Plugin '%s': could not load config file", name); 101 | return STS_FAILURE; 102 | } 103 | 104 | return plugin_regex_body_init(); 105 | } 106 | 107 | /* Processing */ 108 | int PLUGIN_PROCESS(int stage, sip_ticket_t *ticket){ 109 | int sts; 110 | sts=plugin_regex_body_process(ticket); 111 | return sts; 112 | } 113 | 114 | /* De-Initialization */ 115 | int PLUGIN_END(plugin_def_t *plugin_def){ 116 | int i; 117 | int num_entries; 118 | 119 | /* free space for regexes */ 120 | num_entries = plugin_cfg.regex_body_pattern.used; 121 | for (i=0; i < num_entries; i++) { 122 | regfree(&re[i]); 123 | } 124 | free(re); 125 | return STS_SUCCESS; 126 | } 127 | 128 | 129 | /* 130 | * Workload code 131 | */ 132 | static int plugin_regex_body_init(void) { 133 | int i; 134 | int sts, retsts; 135 | int num_entries; 136 | char errbuf[256]; 137 | 138 | retsts = STS_SUCCESS; 139 | 140 | /* check for equal entries of patterns and replacements */ 141 | if (plugin_cfg.regex_body_pattern.used != plugin_cfg.regex_body_replace.used) { 142 | ERROR("Plugin '%s': number of search patterns (%i) and number of " 143 | "replacement patterns (%i) differ!", name, 144 | plugin_cfg.regex_body_pattern.used, plugin_cfg.regex_body_replace.used); 145 | return STS_FAILURE; 146 | } 147 | 148 | if (plugin_cfg.regex_body_pattern.used != plugin_cfg.regex_body_desc.used) { 149 | ERROR("Plugin '%s': number of search patterns (%i) and number of " 150 | "descriptions (%i) differ!", name, 151 | plugin_cfg.regex_body_pattern.used, plugin_cfg.regex_body_desc.used); 152 | return STS_FAILURE; 153 | } 154 | 155 | /* allocate space for regexes and compile them */ 156 | num_entries = plugin_cfg.regex_body_pattern.used; 157 | re = malloc(num_entries*sizeof(re[0])); 158 | for (i=0; i < num_entries; i++) { 159 | sts = regcomp (&re[i], plugin_cfg.regex_body_pattern.string[i], 160 | REG_ICASE|REG_EXTENDED); 161 | if (sts != 0) { 162 | regerror(sts, &re[i], errbuf, sizeof(errbuf)); 163 | ERROR("Regular expression [%s] failed to compile: %s", 164 | plugin_cfg.regex_body_pattern.string[i], errbuf); 165 | retsts = STS_FAILURE; 166 | } 167 | } 168 | 169 | return retsts; 170 | } 171 | 172 | /* code (entry point) */ 173 | static int plugin_regex_body_process(sip_ticket_t *ticket) { 174 | int sts=STS_SUCCESS; 175 | 176 | /* plugin loaded and not configured, return with success */ 177 | if (plugin_cfg.regex_body_pattern.used==0) return STS_SUCCESS; 178 | if (plugin_cfg.regex_body_replace.used==0) return STS_SUCCESS; 179 | 180 | DEBUGC(DBCLASS_PLUGIN,"plugin entered"); 181 | 182 | sts=plugin_regex_body_redirect(ticket); 183 | 184 | return sts; 185 | } 186 | 187 | 188 | /* private plugin code */ 189 | static int plugin_regex_body_redirect(sip_ticket_t *ticket) { 190 | int sts; 191 | osip_message_t *mymsg=ticket->sipmsg; 192 | osip_body_t *body; 193 | char* body_string; 194 | size_t body_length; 195 | char clen[8]; 196 | 197 | #define WORKSPACE_SIZE 1024 198 | static char in[WORKSPACE_SIZE+1], rp[WORKSPACE_SIZE+1]; 199 | 200 | sts = osip_message_get_body(mymsg, 0, &body); 201 | if (sts != 0) { 202 | DEBUGC(DBCLASS_PROXY, "regex_body: no body found in message, skipping"); 203 | return STS_SUCCESS; 204 | } 205 | sts = sip_body_to_str(body, &body_string, &body_length); 206 | 207 | /* perform search and replace of the regexes, first match hits */ 208 | for (int i = 0; i < plugin_cfg.regex_body_pattern.used; i++) { 209 | regmatch_t *pmatch = NULL; 210 | pmatch = rmatch(body_string, WORKSPACE_SIZE, &re[i]); 211 | if (pmatch == NULL) continue; /* no match, next */ 212 | 213 | /* have at least one match, do the replacements */ 214 | INFO("Matched rexec rule: %s",plugin_cfg.regex_body_desc.string[i] ); 215 | strncpy (in, body_string, WORKSPACE_SIZE); 216 | in[WORKSPACE_SIZE]='\0'; 217 | strncpy (rp, plugin_cfg.regex_body_replace.string[i], WORKSPACE_SIZE); 218 | rp[WORKSPACE_SIZE]='\0'; 219 | 220 | for (int match_num = 0; match_num < sizeof(pmatch); match_num++) { 221 | sts = rreplace(in, WORKSPACE_SIZE, &re[i], pmatch, rp); 222 | if (sts != STS_SUCCESS) { 223 | ERROR("regex replace failed: pattern:[%s] replace:[%s]", 224 | plugin_cfg.regex_body_pattern.string[i], 225 | plugin_cfg.regex_body_replace.string[i]); 226 | return STS_FAILURE; 227 | } 228 | } 229 | body_string = in; 230 | } 231 | 232 | sts = osip_list_remove(&(mymsg->bodies), 0); 233 | osip_free(body); 234 | body_length=strlen(body_string); 235 | sip_message_set_body(mymsg, body_string, body_length); 236 | osip_content_length_free(mymsg->content_length); 237 | mymsg->content_length=NULL; 238 | sprintf(clen,"%ld", (long) body_length); 239 | sts = osip_message_set_content_length(mymsg, clen); 240 | 241 | return sts; 242 | } 243 | 244 | /* 245 | * This regex replacement code has been proudly borrowed from 246 | * http://www.daniweb.com/software-development/c/code/216955# 247 | * 248 | * buf: input string + output result 249 | * rp: replacement string, will be destroyed during processing! 250 | * size: size of buf and rp 251 | * re: regex to process 252 | * 253 | * rmatch() performs the initial regexec match, and if a match is found 254 | * it returns a pointer to the regmatch array which contains the result 255 | * of the match. 256 | * Afterwards rreplace() is to be called, providing this regmatch array. 257 | * 258 | * This eliminates the need to copy the 'rp' string before knowing 259 | * if a match is actually there. 260 | */ 261 | #define NMATCHES 10 262 | static regmatch_t * rmatch (char *buf, int size, regex_t *re) { 263 | static regmatch_t pm[NMATCHES]; /* regoff_t is int so size is int */ 264 | 265 | /* perform the match */ 266 | if (regexec (re, buf, NMATCHES, pm, 0)) { 267 | return NULL; 268 | } 269 | return &pm[0]; 270 | } 271 | 272 | static int rreplace (char *buf, int size, regex_t *re, regmatch_t pmatch[], char *rp) { 273 | char *pos; 274 | int sub, so, n; 275 | 276 | /* match(es) found: */ 277 | for (pos = rp; *pos; pos++) { 278 | /* back references \1 ... \9: expand them in 'rp' */ 279 | if (*pos == '\\' && *(pos + 1) > '0' && *(pos + 1) <= '9') { 280 | so = pmatch[*(pos + 1) - 48].rm_so; /* pmatch[1..9] */ 281 | n = pmatch[*(pos + 1) - 48].rm_eo - so; 282 | if (so < 0 || strlen (rp) + n - 1 > size) return STS_FAILURE; 283 | memmove (pos + n, pos + 2, strlen (pos) - 1); 284 | memmove (pos, buf + so, n); 285 | pos = pos + n - 2; 286 | } 287 | } 288 | 289 | sub = pmatch[1].rm_so; /* no repeated replace when sub >= 0 */ 290 | /* and replace rp in the input buffer */ 291 | for (pos = buf; !regexec (re, pos, 1, pmatch, 0); ) { 292 | n = pmatch[0].rm_eo - pmatch[0].rm_so; 293 | pos += pmatch[0].rm_so; 294 | if (strlen (buf) - n + strlen (rp) > size) { 295 | return STS_FAILURE; 296 | } 297 | memmove (pos + strlen (rp), pos + n, strlen (pos) - n + 1); 298 | memmove (pos, rp, strlen (rp)); 299 | pos += strlen (rp); 300 | if (sub >= 0) break; 301 | } 302 | return STS_SUCCESS; 303 | } 304 | -------------------------------------------------------------------------------- /src/plugin_shortdial.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002-2008 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | /* must be defined before including */ 22 | #define PLUGIN_NAME plugin_shortdial 23 | 24 | #include "config.h" 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | 36 | #include "siproxd.h" 37 | #include "plugins.h" 38 | #include "log.h" 39 | 40 | /* Plug-in identification */ 41 | static char name[]="plugin_shortdial"; 42 | static char desc[]="Handles Dial shortcuts as defined in config file"; 43 | 44 | /* global configuration storage - required for config file location */ 45 | extern struct siproxd_config configuration; 46 | 47 | 48 | /* plugin configuration storage */ 49 | static struct plugin_config { 50 | char *shortdial_akey; 51 | stringa_t shortdial_entry; 52 | } plugin_cfg; 53 | /* Instructions for config parser */ 54 | static cfgopts_t plugin_cfg_opts[] = { 55 | { "plugin_shortdial_akey", TYP_STRING, &plugin_cfg.shortdial_akey, {0, NULL} }, 56 | { "plugin_shortdial_entry", TYP_STRINGA,&plugin_cfg.shortdial_entry, {0, NULL} }, 57 | {0, 0, 0} 58 | }; 59 | 60 | 61 | /* local prototypes */ 62 | static int plugin_shortdial_redirect(sip_ticket_t *ticket, int shortcut_no); 63 | static int plugin_shortdial(sip_ticket_t *ticket); 64 | 65 | 66 | /* 67 | * Plugin API functions code 68 | */ 69 | /* Initialization */ 70 | int PLUGIN_INIT(plugin_def_t *plugin_def) { 71 | plugin_def->api_version=SIPROXD_API_VERSION; 72 | plugin_def->name=name; 73 | plugin_def->desc=desc; 74 | plugin_def->exe_mask=PLUGIN_DETERMINE_TARGET; 75 | 76 | /* read the config file */ 77 | if (read_config(configuration.configfile, 78 | configuration.config_search, 79 | plugin_cfg_opts, name) == STS_FAILURE) { 80 | ERROR("Plugin '%s': could not load config file", name); 81 | return STS_FAILURE; 82 | } 83 | 84 | return STS_SUCCESS; 85 | } 86 | 87 | /* Processing */ 88 | int PLUGIN_PROCESS(int stage, sip_ticket_t *ticket){ 89 | int sts; 90 | sts=plugin_shortdial(ticket); 91 | return sts; 92 | } 93 | 94 | /* De-Initialization */ 95 | int PLUGIN_END(plugin_def_t *plugin_def){ 96 | return STS_SUCCESS; 97 | } 98 | 99 | 100 | /* 101 | * Workload code 102 | */ 103 | 104 | /* returns STS_SIP_SENT if processing is to be terminated, 105 | * otherwise STS_SUCCESS (go on with processing) */ 106 | /* code (entry point) */ 107 | static int plugin_shortdial(sip_ticket_t *ticket) { 108 | int sts=STS_SUCCESS; 109 | osip_uri_t *req_url; 110 | int shortcut_no=0; 111 | 112 | /* plugin loaded and not configured, return with success */ 113 | if (plugin_cfg.shortdial_akey==NULL) return STS_SUCCESS; 114 | if (plugin_cfg.shortdial_entry.used==0) return STS_SUCCESS; 115 | 116 | DEBUGC(DBCLASS_PLUGIN,"plugin entered"); 117 | req_url=osip_message_get_uri(ticket->sipmsg); 118 | 119 | /* only outgoing direction is handled */ 120 | sip_find_direction(ticket, NULL); 121 | if (ticket->direction != DIR_OUTGOING) 122 | return STS_SUCCESS; 123 | 124 | /* only INVITE and ACK are handled */ 125 | if (!MSG_IS_INVITE(ticket->sipmsg) && !MSG_IS_ACK(ticket->sipmsg)) 126 | return STS_SUCCESS; 127 | 128 | /* REQ URI with username must exist, length as defined in config, 129 | * shortdial must be enabled and short dial key must match */ 130 | if (!req_url || !req_url->username || 131 | !plugin_cfg.shortdial_akey || 132 | (strlen(req_url->username) != strlen(plugin_cfg.shortdial_akey)) || 133 | (req_url->username[0] != plugin_cfg.shortdial_akey[0])) 134 | return STS_SUCCESS; /* ignore */ 135 | 136 | shortcut_no = atoi(&(req_url->username[1])); 137 | if ((shortcut_no <= 0) || (shortcut_no >= INT_MAX)) return STS_SUCCESS; /* not a number */ 138 | 139 | /* requested number is not defined (out of range) */ 140 | if (shortcut_no > plugin_cfg.shortdial_entry.used) { 141 | DEBUGC(DBCLASS_PLUGIN, "shortdial: shortcut %i > available shortcuts (%i)", 142 | shortcut_no, plugin_cfg.shortdial_entry.used); 143 | return STS_SUCCESS; 144 | } 145 | 146 | /* requested number is not defined (empty) */ 147 | if (!plugin_cfg.shortdial_entry.string[shortcut_no-1]) { 148 | DEBUGC(DBCLASS_PLUGIN, "shortdial: shortcut %i empty", shortcut_no); 149 | return STS_SUCCESS; 150 | } 151 | 152 | /* 153 | * called number does match the short dial specification 154 | */ 155 | 156 | /* outgoing INVITE request */ 157 | if (MSG_IS_INVITE(ticket->sipmsg)) { 158 | DEBUGC(DBCLASS_PLUGIN,"processing INVITE"); 159 | sts=plugin_shortdial_redirect(ticket, shortcut_no); 160 | } 161 | /* outgoing ACK request: is result of a local 3xx answer (moved...) */ 162 | else if (MSG_IS_ACK(ticket->sipmsg)) { 163 | /* make sure we only catch ACKs caused by myself (**02 -> *02 legitime) */ 164 | DEBUGC(DBCLASS_PLUGIN,"processing ACK"); 165 | sts=STS_SIP_SENT; /* eat up the ACK that was directed to myself */ 166 | } 167 | 168 | return sts; 169 | } 170 | 171 | 172 | /* private plugin code */ 173 | static int plugin_shortdial_redirect(sip_ticket_t *ticket, int shortcut_no) { 174 | osip_uri_t *to_url=ticket->sipmsg->to->url; 175 | char *to_user=to_url->username; 176 | char *new_to_user=NULL; 177 | char *new_to_host=NULL; 178 | int i; 179 | size_t username_len; 180 | size_t host_len=0; 181 | osip_contact_t *contact = NULL; 182 | 183 | new_to_user=plugin_cfg.shortdial_entry.string[shortcut_no-1]; 184 | if (!new_to_user) return STS_SUCCESS; 185 | 186 | DEBUGC(DBCLASS_PLUGIN,"redirect: redirecting [%s]->[%s]", 187 | to_user, new_to_user); 188 | 189 | /* use a "302 Moved temporarily" response back to the client */ 190 | /* new target is within the Contact Header */ 191 | 192 | /* remove all Contact headers in message */ 193 | for (i=0; (contact != NULL) || (i == 0); i++) { 194 | osip_message_get_contact(ticket->sipmsg, 0, &contact); 195 | if (contact) { 196 | osip_list_remove(&(ticket->sipmsg->contacts),0); 197 | osip_contact_free(contact); 198 | } 199 | } /* for i */ 200 | 201 | /* get info about new target (user and optional host part) */ 202 | username_len=strlen(new_to_user); /* excluding \0 */ 203 | 204 | /* check if there is an '@' in the shortdial entry */ 205 | new_to_host = strstr(new_to_user, "@"); 206 | if (new_to_host) { 207 | host_len=strlen(new_to_host)-1; /* don't count '@' */ 208 | /* only include the username length */ 209 | username_len = (size_t)(new_to_host-new_to_user); 210 | if (host_len == 0) { 211 | /* if '@' is the last character, then dont rewrite host */ 212 | new_to_host = NULL; 213 | } else { 214 | /* advance one character for the pointer to the host part (skip @) */ 215 | new_to_host++; 216 | } 217 | } 218 | 219 | /* insert one new Contact header containing the new target address */ 220 | osip_contact_init(&contact); 221 | osip_uri_clone(to_url, &contact->url); 222 | 223 | /* USER part is always present */ 224 | osip_free(contact->url->username); 225 | contact->url->username=osip_malloc(username_len+1); /* *_len excluding \0 */ 226 | 227 | /* only copy the part that really belongs to the username */ 228 | strncpy(contact->url->username, new_to_user, username_len); 229 | /* strncpy does not terminate - do it manually */ 230 | contact->url->username[username_len]='\0'; 231 | 232 | /* HOST part is optional */ 233 | if (new_to_host) { 234 | osip_free(contact->url->host); 235 | contact->url->host=osip_strdup(new_to_host); 236 | } 237 | 238 | osip_list_add(&(ticket->sipmsg->contacts),contact,0); 239 | 240 | /* sent redirect message back to local client */ 241 | sip_gen_response(ticket, 302 /*Moved temporarily*/); 242 | 243 | return STS_SIP_SENT; 244 | } 245 | -------------------------------------------------------------------------------- /src/plugin_stripheader.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2015 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warrantry of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | /* must be defined before including */ 22 | #define PLUGIN_NAME plugin_stripheader 23 | 24 | #include "config.h" 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | 36 | #include "siproxd.h" 37 | #include "plugins.h" 38 | #include "log.h" 39 | 40 | /* Plug-in identification */ 41 | static char name[]="plugin_stripheader"; 42 | static char desc[]="Allows removing SIP headers"; 43 | 44 | /* global configuration storage - required for config file location */ 45 | extern struct siproxd_config configuration; 46 | 47 | /* plugin configuration storage */ 48 | static struct plugin_config { 49 | stringa_t header_remove; 50 | } plugin_cfg; 51 | 52 | /* Instructions for config parser */ 53 | static cfgopts_t plugin_cfg_opts[] = { 54 | { "plugin_stripheader_remove", TYP_STRINGA, &plugin_cfg.header_remove, {0, NULL} }, 55 | {0, 0, 0} 56 | }; 57 | 58 | /* 59 | * Initialization. 60 | * Called once suring siproxd startup. 61 | */ 62 | int PLUGIN_INIT(plugin_def_t *plugin_def) { 63 | /* API version number of siproxd that this plugin is built against. 64 | * This constant will change whenever changes to the API are made 65 | * that require adaptions in the plugin. */ 66 | plugin_def->api_version=SIPROXD_API_VERSION; 67 | 68 | /* Name and descriptive text of the plugin */ 69 | plugin_def->name=name; 70 | plugin_def->desc=desc; 71 | 72 | /* Execution mask - during what stages of SIP processing shall 73 | * the plugin be called. */ 74 | plugin_def->exe_mask=PLUGIN_PRE_PROXY; 75 | 76 | /* read the config file */ 77 | if (read_config(configuration.configfile, 78 | configuration.config_search, 79 | plugin_cfg_opts, name) == STS_FAILURE) { 80 | ERROR("Plugin '%s': could not load config file", name); 81 | return STS_FAILURE; 82 | } 83 | 84 | INFO("%s is initialized", name); 85 | return STS_SUCCESS; 86 | } 87 | 88 | /* 89 | * Processing. 90 | * 91 | */ 92 | int PLUGIN_PROCESS(int stage, sip_ticket_t *ticket){ 93 | /* stage contains the PLUGIN_* value - the stage of SIP processing. */ 94 | int i; 95 | int pos; 96 | char *header_remove=NULL; 97 | char *header_remove_args=NULL; 98 | int dlc=65535; /* deadlock counter... - just a life insurance */ 99 | 100 | 101 | 102 | for (i=0; i special cases 116 | * and other headers are stored in a generic header structure 117 | * -> generic headers 118 | */ 119 | 120 | /* special case Allow header */ 121 | if (strcasecmp(header_remove, "allow") == 0) { 122 | osip_allow_t *allow=NULL; 123 | pos=0; 124 | while ((pos = osip_message_get_allow(ticket->sipmsg, 125 | pos, &allow)) != -1) { 126 | if (--dlc <= 0) { ERROR("deadlock counter has triggered. Likely a bug in code."); return STS_FAILURE;} 127 | if (header_remove_args == NULL) { 128 | /* remove all values for header */ 129 | DEBUGC(DBCLASS_PLUGIN, "%s: removing Allow header pos=%i, val=%s", name, 130 | pos, allow->value); 131 | osip_list_remove(&ticket->sipmsg->allows, pos); 132 | osip_allow_free(allow); 133 | allow=NULL; 134 | } else { 135 | /* remove only values "header_remove_args" */ 136 | if (osip_strcasecmp(header_remove_args, allow->value) == 0) { 137 | DEBUGC(DBCLASS_PLUGIN, "%s: removing Allow header value pos=%i, val=%s", name, 138 | pos, allow->value); 139 | osip_list_remove(&ticket->sipmsg->allows, pos); 140 | osip_allow_free(allow); 141 | allow=NULL; 142 | } else { 143 | pos++; 144 | } 145 | } 146 | } 147 | 148 | /* special case: Record-Route headers */ 149 | } else if (strcasecmp(header_remove, "record-route") == 0) { 150 | osip_record_route_t *rroute=NULL; 151 | pos=0; 152 | while ((pos = osip_message_get_record_route(ticket->sipmsg, 153 | pos, &rroute)) != -1) { 154 | if (--dlc <= 0) { ERROR("deadlock counter has triggered. Likely a bug in code."); return STS_FAILURE;} 155 | /* remove all values for header */ 156 | char *tmpstr=NULL; 157 | osip_record_route_to_str(rroute, &tmpstr); 158 | DEBUGC(DBCLASS_PLUGIN, "%s: removing Record-Route header pos=%i, val=%s", name, 159 | pos, tmpstr); 160 | osip_free(tmpstr); 161 | osip_list_remove(&ticket->sipmsg->record_routes, pos); 162 | osip_record_route_free(rroute); 163 | rroute=NULL; 164 | } 165 | 166 | /* generic headers */ 167 | } else { 168 | osip_header_t *h=NULL; 169 | pos=0; 170 | while ((pos = osip_message_header_get_byname(ticket->sipmsg, 171 | header_remove, pos, &h)) != -1) { 172 | if (--dlc <= 0) { ERROR("deadlock counter has triggered. Likely a bug in code."); return STS_FAILURE;} 173 | if (header_remove_args == NULL) { 174 | /* remova all values for header */ 175 | DEBUGC(DBCLASS_PLUGIN, "%s: removing header pos=%i, name=%s, val=%s", name, 176 | pos, h->hname, h->hvalue); 177 | osip_list_remove(&ticket->sipmsg->headers, pos); 178 | osip_header_free(h); 179 | } else { 180 | /* remove only values "header_remove_args" */ 181 | if (osip_strcasecmp(header_remove_args, h->hvalue) == 0) { 182 | DEBUGC(DBCLASS_PLUGIN, "%s: removing header value pos=%i, name=%s, val=%s", name, 183 | pos, h->hname, h->hvalue); 184 | osip_list_remove(&ticket->sipmsg->headers, pos); 185 | osip_header_free(h); 186 | h=NULL; 187 | } else { 188 | pos++; 189 | } 190 | } // if header_remove_args 191 | } 192 | } 193 | 194 | /* free resources */ 195 | if (header_remove_args) { 196 | free (header_remove_args); 197 | header_remove_args = NULL; 198 | } 199 | if (header_remove) { 200 | free (header_remove); 201 | header_remove = NULL; 202 | } 203 | } 204 | 205 | return STS_SUCCESS; 206 | } 207 | 208 | /* 209 | * De-Initialization. 210 | * Called during shutdown of siproxd. Gives the plugin the chance 211 | * to clean up its mess (e.g. dynamic memory allocation, database 212 | * connections, whatever the plugin messes around with) 213 | */ 214 | int PLUGIN_END(plugin_def_t *plugin_def){ 215 | INFO("%s ends here", name); 216 | return STS_SUCCESS; 217 | } 218 | -------------------------------------------------------------------------------- /src/plugin_stun.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hb9xar/siproxd/0bb5dd4aac9f5578db664d82f67091bc83c3780d/src/plugin_stun.c -------------------------------------------------------------------------------- /src/plugins.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2003-2009 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warrantry of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | #include "config.h" 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #include "siproxd.h" 35 | #include "log.h" 36 | #include "plugins.h" 37 | 38 | /* configuration storage */ 39 | extern struct siproxd_config configuration; 40 | 41 | /* Plugin "database" - queue header */ 42 | plugin_def_t *siproxd_plugins=NULL; 43 | 44 | /* code */ 45 | typedef int (*func_plugin_init_t)(plugin_def_t *plugin_def); 46 | typedef int (*func_plugin_process_t)(int stage, sip_ticket_t *ticket); 47 | typedef int (*func_plugin_end_t)(plugin_def_t *plugin_def); 48 | 49 | 50 | /* 51 | * Load the plugins in the order as specified in the config file. 52 | * This is done once, starts with empty plugin list 53 | */ 54 | int load_plugins (void) { 55 | int sts; 56 | int i; 57 | char path[PATH_STRING_SIZE]; 58 | 59 | lt_dlhandle handle=NULL; 60 | plugin_def_t *cur=NULL; 61 | plugin_def_t *last=siproxd_plugins; 62 | 63 | func_plugin_init_t plugin_init = NULL; 64 | func_plugin_process_t plugin_process = NULL; 65 | func_plugin_end_t plugin_end = NULL; 66 | 67 | /* initialize the libtool dynamic loader */ 68 | // LTDL_SET_PRELOADED_SYMBOLS(); 69 | sts = lt_dlinit(); 70 | if (sts != 0) { 71 | ERROR("ltdl (libtool dynamic loader) initialization failed."); 72 | return STS_FAILURE; 73 | } 74 | 75 | /* find plugins to load from config file */ 76 | for (i=0; iname, cur->desc, (sts==STS_SUCCESS)?"success":"failure", 114 | cur->exe_mask); 115 | 116 | /* check return status from plugin - failure leads to unload */ 117 | if (sts != STS_SUCCESS) { 118 | /* complain and unload the plugin */ 119 | ERROR("Plugin '%s' did fail to load.", cur->name); 120 | sts=(*plugin_end)(cur); 121 | free(cur); 122 | continue; 123 | } 124 | 125 | /* check API version that the plugin was biuilt against */ 126 | if (cur->api_version != SIPROXD_API_VERSION) { 127 | /* complain and unload the plugin */ 128 | ERROR("Plugin '%s' does not support correct API version. " 129 | "Please compile plugin with correct siproxd version.", 130 | cur->name); 131 | sts=(*plugin_end)(cur); 132 | free(cur); 133 | continue; 134 | } 135 | 136 | /* store the function pointers */ 137 | cur->plugin_process = plugin_process; 138 | cur->plugin_end = plugin_end; 139 | cur->dlhandle = handle; 140 | 141 | /* store forward pointer */ 142 | if (siproxd_plugins == NULL) { 143 | /* first in chain */ 144 | siproxd_plugins = cur; 145 | last=cur; 146 | cur=NULL; 147 | } else { 148 | /* not first in chain */ 149 | last->next=(void*)cur; 150 | last=cur; 151 | cur=NULL; 152 | } 153 | } else { 154 | /* complain and dlclose the handle...*/ 155 | ERROR("plugin %s does not provide correct API functions - skipped", 156 | configuration.load_plugin.string[i]); 157 | INFO("make sure to specify plugin_.la to load and not the .so!"); 158 | lt_dlclose(handle); 159 | } 160 | } 161 | return STS_SUCCESS; 162 | } 163 | 164 | 165 | /* 166 | * Called at different stages of SIP processing. 167 | */ 168 | int call_plugins(int stage, sip_ticket_t *ticket) { 169 | plugin_def_t *cur; 170 | int sts; 171 | func_plugin_process_t plugin_process; 172 | 173 | /* sanity check, beware plugins from crappy stuff 174 | * applies when SIP message has been parsed */ 175 | if ((stage > PLUGIN_PROCESS_RAW) && (!ticket || !ticket->sipmsg)) return STS_FAILURE; 176 | 177 | /* for each plugin in plugins, do */ 178 | for (cur=siproxd_plugins; cur != NULL; cur = cur->next) { 179 | /* check stage bitmask, if plugin wants to be called do so */ 180 | if (cur->exe_mask & stage) { 181 | plugin_process=cur->plugin_process; 182 | sts=(*plugin_process)(stage, ticket); 183 | switch (stage) { 184 | /* PLUGIN_PROCESS_RAW can be prematurely ended by plugin - 185 | plugin determines that the UDP message is to be discarded */ 186 | case (PLUGIN_PROCESS_RAW): 187 | /* return with the plugins status back to the caller */ 188 | if (sts == STS_FAILURE) { 189 | DEBUGC(DBCLASS_PLUGIN, "call_plugins: PLUGIN_PROCESS_RAW " 190 | "prematurely ending plugin processing in module " 191 | "%s sts=STS_FAILURE", cur->name); 192 | return sts; 193 | } 194 | break; 195 | /* PLUGIN_VALIDATE can be prematurely ended by plugin - 196 | plugin determines that the UDP message is to be discarded */ 197 | case (PLUGIN_VALIDATE): 198 | /* return with the plugins status back to the caller */ 199 | if (sts == STS_FAILURE) { 200 | DEBUGC(DBCLASS_PLUGIN, "call_plugins: PLUGIN_VALIDATE " 201 | "prematurely ending plugin processing in module " 202 | "%s sts=STS_FAILURE", cur->name); 203 | return sts; 204 | } 205 | break; 206 | /* PLUGIN_DETERMINE_TARGET can be prematurely ended by plugin - 207 | plugin processes and sends the final SIP message itself */ 208 | case (PLUGIN_DETERMINE_TARGET): 209 | /* return with the plugins status back to the caller */ 210 | if (sts == STS_SIP_SENT) { 211 | DEBUGC(DBCLASS_PLUGIN, "call_plugins: PLUGIN_DETERMINE_TARGET " 212 | "prematurely ending plugin processing in module " 213 | "%s sts=STS_SIP_SENT", cur->name); 214 | return sts; 215 | } 216 | break; 217 | default: 218 | break; 219 | } /* switch*/ 220 | } /* if */ 221 | } /* for */ 222 | 223 | return STS_SUCCESS; 224 | } 225 | 226 | 227 | /* 228 | * At termination of siproxd "unloads" the plugins. 229 | * Actually gives the plugins the chance to cleanup whatever they want. 230 | * The plugins are called in reversed order of loading (last loaded is 231 | * unloaded first). 232 | */ 233 | int unload_plugins(void) { 234 | plugin_def_t *cur, *last; 235 | int sts; 236 | func_plugin_end_t plugin_end; 237 | 238 | /* for each plugin in plugins do (start at the end of the plugin list) */ 239 | DEBUGC(DBCLASS_PLUGIN, "unloading dynamic plugins"); 240 | 241 | /* call plugin_end function - the plugin may need to cleanup as well... */ 242 | while (siproxd_plugins) { 243 | /* search the end */ 244 | last=NULL; 245 | for (cur=siproxd_plugins; cur->next != NULL; cur = cur->next) {last=cur;} 246 | 247 | plugin_end=cur->plugin_end; 248 | DEBUGC(DBCLASS_PLUGIN, "unload_plugins: '%s' unloading ptr=%p", 249 | cur->name, cur); 250 | sts=(*plugin_end)(cur); 251 | DEBUGC(DBCLASS_PLUGIN, "unload_plugins: status=%s", 252 | (sts==STS_SUCCESS)?"success":"failure"); 253 | 254 | /* dlclose */ 255 | sts = lt_dlclose(cur->dlhandle); 256 | if (sts != 0) { 257 | ERROR("lt_dlclose() failed, ptr=%p", cur); 258 | } 259 | 260 | /* deallocate plugins list item */ 261 | if (last) last->next=NULL; 262 | free(cur); 263 | 264 | /* I don't like this */ 265 | if (cur == siproxd_plugins) siproxd_plugins=NULL; 266 | } 267 | 268 | /* shutdown ltdl */ 269 | sts = lt_dlexit(); 270 | if (sts != 0) { 271 | ERROR("lt_dlexit() failed"); 272 | } 273 | 274 | return STS_SUCCESS; 275 | } 276 | -------------------------------------------------------------------------------- /src/plugins.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002-2009 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | /* $Id$ */ 22 | 23 | #include 24 | 25 | #ifdef WITH_LTDL_FIX 26 | /* workaround for some broken libtool 2.2.6 (and others?) versions 27 | * that cause an 28 | * undefined reference to `lt__PROGRAM__LTX_preloaded_symbols' 29 | * error during linking state */ 30 | #ifndef lt__PROGRAM__LTX_preloaded_symbols 31 | #define lt__PROGRAM__LTX_preloaded_symbols lt_libltdl_LTX_preloaded_symbols 32 | #endif 33 | #endif 34 | 35 | 36 | /* Plugins must return STS_SUCCESS / SUCCESS_FAILURE */ 37 | 38 | 39 | /* 40 | * Processing stages for Plugins 41 | */ 42 | /* NOOP */ 43 | /* No activation */ 44 | #define PLUGIN_NOOP 0x00000000 45 | 46 | /* get cyclic trigger */ 47 | /* NO ticket is present (ticket = NULL pointer) */ 48 | #define PLUGIN_TIMER 0x00000001 49 | 50 | /* Process RAW data received */ 51 | /* may end the current SIP processing in siproxd by returning STS_FALSE * 52 | * may be used to intercept other traffic on SIP port */ 53 | /* ticket with NO sipmsg is present (ticket.sipmsg = NULL pointer) */ 54 | #define PLUGIN_PROCESS_RAW 0x00000008 55 | 56 | /*--------- below here a valid sip message (ticket->sipmsg) is present ---*/ 57 | 58 | /* Validation of SIP packet */ 59 | /* may end the current SIP processing in siproxd by returning STS_FALSE/STS_FAILURE * 60 | * may be used to intercept other traffic on SIP port */ 61 | #define PLUGIN_VALIDATE 0x00000010 62 | 63 | /* Determining Request Targets */ 64 | /* may end the current SIP processing in siproxd by returning STS_SIP_SENT 65 | * see plugin_shortcut that sends a redirect back to the client */ 66 | #define PLUGIN_DETERMINE_TARGET 0x00000020 /* Determining Request Targets */ 67 | 68 | /* SIP package before siproxd starts the proxying process */ 69 | #define PLUGIN_PRE_PROXY 0x00000040 /* before MASQuerading */ 70 | 71 | /* to/from unregistered UA */ 72 | #define PLUGIN_PROXY_UNK 0x00000080 /* e.g. incoming call to unknown UA */ 73 | 74 | /* before sending the SIP message */ 75 | #define PLUGIN_POST_PROXY 0x00000100 /* after MASQuerading */ 76 | 77 | 78 | /* Plugin "database" */ 79 | typedef struct { 80 | void *next; /* link to next plugin element, NULL if last */ 81 | int api_version; /* API version that PLUGIN uses */ 82 | char *name; /* Plugin name */ 83 | char *desc; /* Description */ 84 | int exe_mask; /* bitmask for activation of different processing 85 | stages during SIP processing that a plugin wants 86 | to be called */ 87 | lt_ptr plugin_process;/* Plugin processing entry point */ 88 | lt_ptr plugin_end; /* de-initialization function */ 89 | lt_ptr dlhandle; /* handle returned by dlopen() */ 90 | } plugin_def_t; 91 | 92 | #define SIPROXD_API_VERSION 0x0102 93 | 94 | 95 | /* The plugin must provide the following entry points */ 96 | /* Plugin is responsable for its dynamic memory management. 97 | - Storage allocated in _init must be released in _end. 98 | - manipulation of SIP messages (sip_ticket structure) must 99 | be made in a way to ensure that no memleaks do exist. 100 | If you want to change a field, first osip_malloc() new space, 101 | move the pointer in the osip structure to the new place and then 102 | osip_free() the old area. 103 | */ 104 | /* plugin_init must define the following fields of the plugin_def_t structure: 105 | - api_version (= SIPROXD_API_VERSION) 106 | - name 107 | - desc 108 | - exe_mask 109 | The rest will be initialized by siproxd and must not be fumbled with. 110 | */ 111 | int plugin_init(plugin_def_t *plugin_def); 112 | int plugin_process(int stage, sip_ticket_t *ticket); 113 | int plugin_end(plugin_def_t *plugin_def); 114 | 115 | /* libltdl symbol name magic... 116 | convert plugin_init into _LTX_plugin_init */ 117 | 118 | #if defined (PLUGIN_NAME) 119 | #define JOIN(x, y) JOIN_AGAIN(x, y) 120 | #define JOIN_AGAIN(x, y) x ## y 121 | #define PLUGIN_INIT JOIN(PLUGIN_NAME, _LTX_plugin_init) 122 | #define PLUGIN_PROCESS JOIN(PLUGIN_NAME, _LTX_plugin_process) 123 | #define PLUGIN_END JOIN(PLUGIN_NAME, _LTX_plugin_end) 124 | #endif 125 | -------------------------------------------------------------------------------- /src/redirect_cache.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002-2011 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #include "siproxd.h" 35 | #include "redirect_cache.h" 36 | #include "log.h" 37 | 38 | #define CACHE_TIMEOUT 20 39 | 40 | /* 41 | * Helper for siproxd plugins that operate with 302 redirection 42 | * like the plugin_shortdial, plugin_prefix or plugin_regex . 43 | * 44 | * The plugin must consume the ACK from the local UA caused by the 45 | * 302 Moved response. No other ACKs must be dropped by the plugin. 46 | * 47 | * The recommended way is that upon sending a "302 Moved" response 48 | * towards the local UA, the plugin does put the Call-Id of this 49 | * dialog into a cache. Any ACK with matching Call-Id will be dropped 50 | * (consumed by the plugin) but nothing more. 51 | * 52 | * Below is a set of 3 functions to implement this functionality 53 | * inside a plugin. The whole SIP ticket will be passed, so 54 | * modifying the matching criteria can be easily done, transparent 55 | * to the plugins. 56 | * 57 | * This is the "redirected_cache". Each plugin needs its own private 58 | * cache. A static Queue header for the cache must be created and 59 | * passed to the cache handling functions. 60 | * 61 | * static redirected_cache_element_t redirected_cache; 62 | * [...] 63 | * add_to_redirected_cache(&redirected_cache, ticket); 64 | * 65 | */ 66 | 67 | int add_to_redirected_cache(redirected_cache_element_t *redirected_cache, sip_ticket_t *ticket) { 68 | redirected_cache_element_t *e; 69 | DEBUGC(DBCLASS_PLUGIN, "entered add_to_redirected_cache()"); 70 | 71 | /* allocate */ 72 | e=malloc(sizeof(redirected_cache_element_t)); 73 | if (e == NULL) { 74 | ERROR("out of memory"); 75 | return STS_FAILURE; 76 | } 77 | 78 | /* populate element */ 79 | e->next = NULL; 80 | e->ts = time(NULL); 81 | osip_call_id_clone(ticket->sipmsg->call_id, &(e->call_id)); 82 | 83 | /* add to head of queue */ 84 | e->next = redirected_cache->next; 85 | redirected_cache->next = e; 86 | 87 | DEBUGC(DBCLASS_PLUGIN, "left add_to_redirected_cache()"); 88 | return STS_SUCCESS; 89 | } 90 | 91 | int is_in_redirected_cache(redirected_cache_element_t *redirected_cache, sip_ticket_t *ticket) { 92 | redirected_cache_element_t *p, *p_prev; 93 | 94 | DEBUGC(DBCLASS_BABBLE, "entered is_in_redirected_cache"); 95 | /* iterate through queue */ 96 | p_prev=NULL; 97 | for (p=redirected_cache; p; p=p->next) { 98 | DEBUGC(DBCLASS_BABBLE, "l: p=%p, p->next=%p", p, p->next); 99 | if ( (p != redirected_cache) && (p_prev != NULL) ) { 100 | if (compare_callid(ticket->sipmsg->call_id, p->call_id) == STS_SUCCESS) { 101 | DEBUGC(DBCLASS_BABBLE, "remove p=%p", p); 102 | /* remove from queue */ 103 | p_prev->next = p->next; 104 | osip_call_id_free (p->call_id); 105 | free(p); 106 | DEBUGC(DBCLASS_BABBLE, "left is_in_redirected_cache - FOUND"); 107 | return STS_TRUE; 108 | } /* if compare_callid */ 109 | } 110 | p_prev = p; 111 | } /* for */ 112 | DEBUGC(DBCLASS_BABBLE, "left is_in_redirected_cache - NOT FOUND"); 113 | return STS_FALSE; 114 | } 115 | 116 | /* 117 | * Run through the whole Call-Id cache and remove 118 | * expired elements. 119 | */ 120 | int expire_redirected_cache(redirected_cache_element_t *redirected_cache) { 121 | redirected_cache_element_t *p, *p_prev; 122 | time_t now; 123 | 124 | DEBUGC(DBCLASS_BABBLE, "entered expire_redirected_cache"); 125 | now = time(NULL); 126 | 127 | /* iterate through queue */ 128 | p_prev=NULL; 129 | for (p=redirected_cache; p; p=p->next) { 130 | DEBUGC(DBCLASS_BABBLE, "1: p=%p, p->next=%p", p, p->next); 131 | if ( (p != redirected_cache) && (p_prev != NULL) ) { 132 | DEBUGC(DBCLASS_BABBLE,"ts:%i, now:%i", (int)p->ts, (int)now); 133 | if ((p->ts + CACHE_TIMEOUT) < now) { 134 | DEBUGC(DBCLASS_BABBLE, "remove p=%p", p); 135 | /* remove from queue */ 136 | p_prev->next = p->next; 137 | osip_call_id_free (p->call_id); 138 | free(p); 139 | /* the current element is being removed and invalidated, 140 | * set the iteration pointer to a valid element. */ 141 | p = p_prev; 142 | } /* if timeout */ 143 | DEBUGC(DBCLASS_BABBLE, "2: p=%p, p->next=%p", p, p->next); 144 | } 145 | p_prev = p; 146 | } /* for */ 147 | DEBUGC(DBCLASS_BABBLE, "left expire_redirected_cache"); 148 | return STS_FALSE; 149 | } 150 | -------------------------------------------------------------------------------- /src/redirect_cache.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | /* $Id: siproxd.h 482 2011-06-12 18:45:17Z hb9xar $ */ 22 | 23 | typedef struct { 24 | void *next; 25 | osip_call_id_t *call_id; 26 | time_t ts; 27 | } redirected_cache_element_t; 28 | 29 | /* return STS_ codes */ 30 | int add_to_redirected_cache(redirected_cache_element_t *redirected_cache, 31 | sip_ticket_t *ticket); 32 | int is_in_redirected_cache( redirected_cache_element_t *redirected_cache, 33 | sip_ticket_t *ticket); 34 | int expire_redirected_cache(redirected_cache_element_t *redirected_cache); 35 | -------------------------------------------------------------------------------- /src/resolve.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005-2008 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | #ifdef __APPLE__ 28 | #include 29 | #endif 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "log.h" 37 | 38 | #define USE_NAPTR 0 39 | 40 | /* local functions */ 41 | static int _resolve(char *name, int class, int type, 42 | char *dname, int dnamelen, int *port); 43 | 44 | /* 45 | * perform a SRV record lookup 46 | * 47 | * name name of service 48 | * proto IPPROTO_TCP / IPPROTO_UDP 49 | * dname returned value 50 | * dnamelen length of return buffer 51 | * port port number of service 52 | */ 53 | int resolve_SRV(char *name, int proto, char *dname, int dnamelen, int *port) { 54 | char nname[256]; 55 | if (proto == IPPROTO_TCP) { 56 | snprintf(nname, sizeof(nname), "_sip._tcp.%s", name); 57 | } else { 58 | snprintf(nname, sizeof(nname), "_sip._udp.%s", name); 59 | } 60 | return _resolve(nname, C_IN, T_SRV, dname, dnamelen, port); 61 | } 62 | 63 | #if USE_NAPTR 64 | /* 65 | * perform a NAPTR lookup 66 | * 67 | * name name of service 68 | * dname return 69 | * dnamelen length of return buffer 70 | */ 71 | int resolve_NAPTR(char *name, char *dname, int dnamelen) { 72 | int port=0; 73 | return _resolve(name, C_ANY, T_NAPTR, dname, dnamelen, &port); 74 | } 75 | #endif 76 | 77 | /* 78 | * query the DNS for a specific record type 79 | */ 80 | static int _resolve(char *name, int class, int type, 81 | char *dname, int dnamelen, int *port) { 82 | int sts; 83 | 84 | 85 | // message buffer 86 | unsigned char msg[PACKETSZ]; 87 | int msglen=PACKETSZ; 88 | 89 | // response header 90 | HEADER *res_header; 91 | 92 | // expanded name 93 | char exp_dn[MAXDNAME]; 94 | int exp_dnlen=MAXDNAME; 95 | 96 | int i, j, co; 97 | unsigned char *mptr, *xptr; 98 | unsigned short *usp,ty; 99 | unsigned int *uip; 100 | 101 | u_short priority = 0; 102 | u_short weight = 0; 103 | 104 | char tmpname[PACKETSZ]; 105 | 106 | dname[0]='\0'; 107 | *port=0; 108 | 109 | // issue request 110 | sts=res_query(name, class, type, msg, msglen); 111 | if (sts<0) { 112 | ERROR("res_query failed sts=%i\n", sts); 113 | return 0; 114 | } 115 | 116 | res_header = (HEADER *)msg; 117 | DEBUGC(DBCLASS_DNS, "_resolve: name=[%s], type=%i, qdcount=%i, ancount=%i", 118 | name, type, ntohs(res_header->qdcount), ntohs(res_header->ancount)); 119 | 120 | mptr=msg+sizeof(HEADER); 121 | 122 | // loop through query part 123 | co=ntohs(res_header->qdcount); 124 | for (i=0; iancount); 140 | for (i=0; i weight) ) { 180 | priority = pr; 181 | weight = we; 182 | *port = po; 183 | strncpy(dname, tmpname, dnamelen); 184 | /*&&& here the magic with the priorities should go. 185 | which one do we use? RFC3263 talks a bit on how a stateless 186 | SIP proxy should handle it - BY GOING STATEFUL if the lowest priority 187 | is unavailable. Why do I have a stateless proxy? Exactly, because I 188 | do NOT want to do the whole stateful crap. 189 | Rethinking needed. 190 | Currently just the first (lowest prio, highest weight) entry is returned. 191 | */ 192 | xptr+=j; 193 | } 194 | } 195 | #if USE_NAPTR 196 | } else if( ty == T_NAPTR ) { 197 | DEBUGC(DBCLASS_DNS, "_resolve: A - type NAPTR"); 198 | usp = (unsigned short *)xptr; 199 | xptr += sizeof(short); 200 | usp = (unsigned short *)xptr; 201 | xptr += sizeof(short); 202 | j = (int)(*xptr); 203 | xptr += 1; 204 | while( j > 0 ) { 205 | xptr+=1; 206 | j--; 207 | } 208 | j = (int)(*xptr); 209 | xptr += 1; 210 | while( j > 0 ) { 211 | xptr += 1; 212 | j--; 213 | } 214 | j=(int)(*xptr); 215 | xptr+=1; 216 | while( j > 0 ) { 217 | xptr += 1; 218 | j--; 219 | } 220 | j = dn_expand( msg, msg + PACKETSZ, xptr, tmpname, MAXDNAME ); 221 | if( j < 0 ) { 222 | break; 223 | } else { 224 | /* 225 | * there should be some REGEX magic, no? 226 | * Not yet used nor implemented. Just complain in 227 | * case somebody feels lucky enough trying to use it. 228 | */ 229 | ERROR("_resolve: NAPTR lookup not yet supported."); 230 | if( proto == PROTO_UDP ) { 231 | if( strstr(tmpname, "_udp" ) ) { 232 | strncpy(dname, tmpname, dnamelen); 233 | } 234 | } else { 235 | if( strstr(tmpname, "_tcp" ) ) { 236 | strncpy(dname, tmpname, dnamelen); 237 | } 238 | } 239 | DEBUGC(DBCLASS_DNS, "_resolve: A[%i] - type NAPTR: %s", 240 | i, tmpname); 241 | xptr+=j; 242 | } 243 | #endif 244 | } else { 245 | ERROR("_resolve: unknown type in DNS answer [type=%i]\n", ty); 246 | } // if ty 247 | } // if dn_expand 248 | } // for i 249 | 250 | dname[dnamelen-1]='\0'; 251 | return 0; 252 | } 253 | 254 | -------------------------------------------------------------------------------- /src/rtpproxy.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2003-2009 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | #include "siproxd.h" 30 | #include "rtpproxy.h" 31 | #include "log.h" 32 | 33 | /* configuration storage */ 34 | extern struct siproxd_config configuration; 35 | 36 | /* 37 | * initialize and create rtp_proxy 38 | * 39 | * RETURNS 40 | * STS_SUCCESS on success 41 | */ 42 | int rtpproxy_init( void ) { 43 | int sts=STS_FAILURE; 44 | 45 | if (configuration.rtp_proxy_enable == 0) { 46 | sts = STS_SUCCESS; 47 | } else if (configuration.rtp_proxy_enable == 1) { // Relay 48 | sts = rtp_relay_init (); 49 | if ((configuration.rtp_output_dejitter < 0) || 50 | (configuration.rtp_output_dejitter > DEJITTERLIMIT)) { 51 | ERROR("CONFIG: rtp_output_dejitter has invalid value %i [0 .. %i]", 52 | configuration.rtp_output_dejitter, DEJITTERLIMIT) ; 53 | } 54 | if ((configuration.rtp_input_dejitter < 0) || 55 | (configuration.rtp_input_dejitter > DEJITTERLIMIT)) { 56 | ERROR("CONFIG: rtp_input_dejitter has invalid value %i [0 .. %i]", 57 | configuration.rtp_input_dejitter, DEJITTERLIMIT) ; 58 | } 59 | } else { 60 | ERROR("CONFIG: rtp_proxy_enable has invalid value: %d", 61 | configuration.rtp_proxy_enable); 62 | } 63 | 64 | return sts; 65 | } 66 | 67 | /* 68 | * start an rtp stream on the proxy 69 | * 70 | * RETURNS 71 | * STS_SUCCESS on success 72 | * STS_FAILURE on error 73 | */ 74 | int rtp_start_fwd (osip_call_id_t *callid, client_id_t client_id, 75 | int direction, int call_direction, int media_stream_no, 76 | struct in_addr local_ipaddr, int *local_port, 77 | struct in_addr remote_ipaddr, int remote_port, 78 | int isrtp, int cseq) { 79 | int sts=STS_FAILURE; 80 | int dejitter=0; 81 | 82 | if (configuration.rtp_proxy_enable == 0) { 83 | sts = STS_SUCCESS; 84 | } else if (configuration.rtp_proxy_enable == 1) { // Relay 85 | if (isrtp) { 86 | if (direction == DIR_OUTGOING) { 87 | dejitter = configuration.rtp_output_dejitter; 88 | } else { 89 | dejitter = configuration.rtp_input_dejitter; 90 | } 91 | } 92 | sts = rtp_relay_start_fwd (callid, client_id, 93 | direction, call_direction, media_stream_no, 94 | local_ipaddr, local_port, 95 | remote_ipaddr, remote_port, dejitter, 96 | cseq); 97 | } else { 98 | ERROR("CONFIG: rtp_proxy_enable has invalid value: %d", 99 | configuration.rtp_proxy_enable); 100 | } 101 | 102 | return sts; 103 | } 104 | 105 | 106 | /* 107 | * stop a rtp stream on the proxy 108 | * 109 | * RETURNS 110 | * STS_SUCCESS on success 111 | * STS_FAILURE on error 112 | */ 113 | int rtp_stop_fwd (osip_call_id_t *callid, int direction, int cseq) { 114 | int sts = STS_FAILURE; 115 | 116 | if (configuration.rtp_proxy_enable == 0) { 117 | sts = STS_SUCCESS; 118 | } else if (configuration.rtp_proxy_enable == 1) { // Relay 119 | sts = rtp_relay_stop_fwd(callid, direction, -1, cseq, LOCK_FDSET); 120 | } else { 121 | ERROR("CONFIG: rtp_proxy_enable has invalid value: %d", 122 | configuration.rtp_proxy_enable); 123 | } 124 | 125 | return sts; 126 | } 127 | -------------------------------------------------------------------------------- /src/rtpproxy.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hb9xar/siproxd/0bb5dd4aac9f5578db664d82f67091bc83c3780d/src/rtpproxy.h -------------------------------------------------------------------------------- /src/sip_layer.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002-2008 Thomas Ries 3 | 4 | This file is part of Siproxd. 5 | 6 | Siproxd is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | Siproxd is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Siproxd; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | /* 25 | * This file contains wrapper functions to call the osip2_ library. 26 | * depending on the used version of libosip2, the calling arguments 27 | * differ. E.g. Libosip2-2.2.0 (against 2.0.9) introduces a "size" 28 | * argument for a number of functions used by siproxd. 29 | */ 30 | 31 | int sip_message_parse(osip_message_t * sip, const char *buf, size_t len) { 32 | return osip_message_parse(sip, buf, len); 33 | } 34 | 35 | int sip_message_to_str(osip_message_t * sip, char **dest, size_t *len) { 36 | int sts; 37 | /* check params */ 38 | if ((len == NULL) || (dest == NULL)) return -1; 39 | 40 | *len=0; 41 | 42 | sts = osip_message_to_str(sip, dest, len); 43 | if (sts == 0) { 44 | /* 45 | * NULL termination (libosip2-2.2.0 does NOT do this properly, 46 | * there is always one byte too much :-( ) 47 | */ 48 | if (*len >= 0) (*dest)[*len]='\0'; 49 | } 50 | 51 | return sts; 52 | } 53 | 54 | int sip_body_to_str(const osip_body_t * body, char **dest, size_t *len) { 55 | int sts; 56 | /* check params */ 57 | if ((len == NULL) || (dest == NULL)) return -1; 58 | 59 | *len=0; 60 | 61 | sts = osip_body_to_str(body, dest, len); 62 | if (sts == 0) { 63 | /* 64 | * NULL termination (libosip2-2.2.0 does NOT do this properly, 65 | * there is always one byte too much :-( ) 66 | */ 67 | if (*len >= 0) (*dest)[*len]='\0'; 68 | } 69 | 70 | return sts; 71 | } 72 | 73 | int sip_message_set_body(osip_message_t * sip, const char *buf, size_t len) { 74 | return osip_message_set_body(sip, buf, len); 75 | } 76 | 77 | -------------------------------------------------------------------------------- /stamp-h.in: -------------------------------------------------------------------------------- 1 | timestamp 2 | -------------------------------------------------------------------------------- /tools/extract_sip.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # 4 | # extract a buffer dump from siproxd's debug log and 5 | # write the plain content into a file. This file then 6 | # may be used to feed netcat for a replay.# 7 | # 8 | # $ netcat -u siphost 5060 < buffer.sip 9 | # 10 | # usage: 11 | # reads from STDIN and writes to STDOUT 12 | # 13 | # $ cat bufferdump.log | extract_sip.pl > buffer.sip 14 | 15 | while (<>) { 16 | # strip off CR/LF 17 | chomp; 18 | 19 | # cut out the hex digits and store them into an array 20 | my $line=$_; 21 | $line =~ s/^ *//; 22 | my @hex=split(/ /, substr($line, 0, 50)); 23 | 24 | for (my $i=0; $i<16; $i++) { 25 | # write HEX byte as character 26 | if (hex($hex[$i]) != "") {print chr(hex($hex[$i]));} 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tools/sipp_testing/README: -------------------------------------------------------------------------------- 1 | 2 | Setup: 3 | ------ 4 | 5 | HOSTA ---------- siproxd ------------HOSTB 6 | private net | Internet 7 | 8 | 9 | siproxd must be setup as transparent proxy (iptables rules to 10 | redirect all outgoing SIP traffic from sipp to HOSTB to local siproxd) 11 | 12 | Client on HOSTA 13 | --------------- 14 | - limited to 10 simultaneous calls (-> default configured RTP port range) 15 | - server and client are on port 5070 16 | - each call is kept for 1000ms (-d), then terminated 17 | - every 1000ms (-rp) 5 (-r) new calls are spawned 18 | - end test after 100 total calls 19 | 20 | ./sipp -sf myuac.xml -l 10 -p 5070 -d 1000 \ 21 | -m 100 -r 5 -rp 1000 HOSTB:5070 22 | 23 | 24 | Server on HOSTB 25 | --------------- 26 | - port 5070 27 | 28 | ./sipp -sf myuas.xml -p 5070 29 | 30 | 31 | Note: siproxd has limited simultaneous calls 32 | - RTP port range 33 | - some compile time constants for RTP array sizing 34 | 35 | Those XML scenarios include a REGISTER step before doing the 36 | actual call. This is required for siproxd to know the local UA. 37 | -------------------------------------------------------------------------------- /tools/sipp_testing/myuac.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ;tag=[pid]SIPpTag07[call_number] 18 | To: sipp 19 | Call-ID: [call_id] 20 | CSeq: 1 REGISTER 21 | Contact: 22 | Content-Length: 0 23 | Expires: 300 24 | 25 | ]]> 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | ;tag=[pid]SIPpTag00[call_number] 38 | To: sut 39 | Call-ID: [call_id] 40 | CSeq: 1 INVITE 41 | Contact: 42 | Max-Forwards: 70 43 | Subject: Performance Test 44 | Content-Type: application/sdp 45 | Content-Length: 151 46 | 47 | v=0 48 | o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] 49 | s=session 50 | c=IN IP[media_ip_type] [media_ip] 51 | t=0 0 52 | m=audio [media_port] RTP/AVP 0 53 | a=rtpmap:0 PCMU/8000 54 | a=ptime:20 55 | 56 | 57 | foo 58 | ]]> 59 | 60 | 61 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | ;tag=[pid]SIPpTag00[call_number] 85 | To: sut [peer_tag_param] 86 | Call-ID: [call_id] 87 | CSeq: 1 ACK 88 | Contact: 89 | Max-Forwards: 70 90 | Subject: Performance Test 91 | Content-Length: 0 92 | 93 | ]]> 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | ;tag=[pid]SIPpTag00[call_number] 107 | To: sut [peer_tag_param] 108 | Call-ID: [call_id] 109 | CSeq: 2 BYE 110 | Contact: 111 | Max-Forwards: 70 112 | Subject: Performance Test 113 | Content-Length: 0 114 | 115 | ]]> 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /tools/sipp_testing/myuas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 23 | Content-Length: 0 24 | Expires: 300 25 | ]]> 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 57 | Content-Length: 0 58 | 59 | ]]> 60 | 61 | 62 | 63 | 64 | 73 | Content-Type: application/sdp 74 | Content-Length: 155 75 | 76 | v=0 77 | o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] 78 | s=session 79 | c=IN IP[media_ip_type] [media_ip] 80 | t=0 0 81 | m=audio [media_port] RTP/AVP 0 82 | a=rtpmap:0 PCMU/8000 83 | a=ptime:20 84 | 85 | foo 86 | ]]> 87 | 88 | 89 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 108 | Content-Length: 0 109 | 110 | ]]> 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | --------------------------------------------------------------------------------