Module: sip-router Branch: andrei/raw_sock Commit: 22e7e32e343724a42abc4c0c1b7986e88e50111b URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=22e7e32e...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@iptel.org Date: Tue Jun 15 16:36:14 2010 +0200
raw sockets: udp send will use now raw sockets if enabled
A raw socket, that will be used for sending, is now initialized on startup. The operation can succeed only if sr is started as root or with CAP_NET_RAW. If the initialization fails and the raw sockets are forced on from the config (udp4_raw = 1), ser won't start. If the raw socket are in auto mode (udp4_raw = -1), sr will start, but with the raw socket send part disabled (normal udp send will be used).
If the raw socket part is not disabled at startup, it can be turned anytime on/off via the runtime cfg. framework.
Note: the raw socket send is supported only over ipv4 and for now only on linux.
---
main.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++------- udp_server.c | 69 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 119 insertions(+), 29 deletions(-)
diff --git a/main.c b/main.c index 7d28bcd..a90e855 100644 --- a/main.c +++ b/main.c @@ -73,16 +73,15 @@ * 2008-08-08 sctp support (andrei) * 2008-08-19 -l support for mmultihomed addresses/addresses lists * (e.g. -l (eth0, 1.2.3.4, foo.bar) ) (andrei) - * 2010-04-19 added daemon_status_fd pipe to communicate the parent process with - the main process in daemonize mode, so the parent process can return - the proper exit status code (ibc) + * 2010-04-19 added daemon_status_fd pipe to communicate the parent process + * with the main process in daemonize mode, so the parent process + * can return the proper exit status code (ibc) */
-/*! - * \file - * \brief SIP-router core :: - * \ingroup core - * Module: \ref core +/** intializations and startup. + * @file main.c + * @ingroup core + * Module: @ref core */
/*! \defgroup core SIP-router core @@ -148,6 +147,9 @@ #include "nonsip_hooks.h" #include "ut.h" #include "signals.h" +#ifdef USE_RAW_SOCKS +#include "raw_sock.h" +#endif /* USE_RAW_SOCKS */ #ifdef USE_TCP #include "poll_types.h" #include "tcp_init.h" @@ -439,6 +441,9 @@ struct socket_info* bind_address=0; /* pointer to the crt. proc. listening address*/ struct socket_info* sendipv4; /* ipv4 socket to use when msg. comes from ipv6*/ struct socket_info* sendipv6; /* same as above for ipv6 */ +#ifdef USE_RAW_SOCKS +int raw_udp4_send_sock = -1; /* raw socket used for sending udp4 packets */ +#endif /* USE_RAW_SOCKS */ #ifdef USE_TCP struct socket_info* sendipv4_tcp; struct socket_info* sendipv6_tcp; @@ -1237,9 +1242,35 @@ int main_loop() /* only one address, we ignore all the others */ if (udp_init(udp_listen)==-1) goto error; bind_address=udp_listen; - if (bind_address->address.af==AF_INET) + if (bind_address->address.af==AF_INET) { sendipv4=bind_address; - else +#ifdef USE_RAW_SOCKS + /* always try to have a raw socket opened if we are using ipv4 */ + raw_udp4_send_sock = raw_socket(IPPROTO_RAW, 0, 0, 1); + if (raw_udp4_send_sock < 0) { + if ( default_core_cfg.udp4_raw > 0) { + /* force use raw socket failed */ + ERR("could not initialize raw udp send socket (ipv4):" + " %s (%d)\n", strerror(errno), errno); + if (errno == EPERM) + ERR("could not initialize raw socket on startup" + " due to inadequate permissions, please" + " restart as root or with CAP_NET_RAW\n"); + goto error; + } + default_core_cfg.udp4_raw = 0; /* disabled */ + } else { + register_fds(1); + if (default_core_cfg.udp4_raw < 0) { + /* auto-detect => use it */ + default_core_cfg.udp4_raw = 1; /* enabled */ + DBG("raw socket possible => turning it on\n"); + } + } +#else + default_core.cfg.udp4_raw = 0; +#endif /* USE_RAW_SOCKS */ + } else sendipv6=bind_address; if (udp_listen->next){ LOG(L_WARN, "WARNING: using only the first listen address" @@ -1363,6 +1394,34 @@ int main_loop() /* children_no per each socket */ cfg_register_child(children_no); } +#ifdef USE_RAW_SOCKS + /* always try to have a raw socket opened if we are using ipv4 */ + if (sendipv4) { + raw_udp4_send_sock = raw_socket(IPPROTO_RAW, 0, 0, 1); + if (raw_udp4_send_sock < 0) { + if ( default_core_cfg.udp4_raw > 0) { + /* force use raw socket failed */ + ERR("could not initialize raw udp send socket (ipv4):" + " %s (%d)\n", strerror(errno), errno); + if (errno == EPERM) + ERR("could not initialize raw socket on startup" + " due to inadequate permissions, please" + " restart as root or with CAP_NET_RAW\n"); + goto error; + } + default_core_cfg.udp4_raw = 0; /* disabled */ + } else { + register_fds(1); + if (default_core_cfg.udp4_raw < 0) { + /* auto-detect => use it */ + default_core_cfg.udp4_raw = 1; /* enabled */ + DBG("raw socket possible => turning it on\n"); + } + } + } +#else + default_core_cfg.udp4_raw = 0; +#endif /* USE_RAW_SOCKS */ #ifdef USE_SCTP if (!sctp_disable){ for(si=sctp_listen; si; si=si->next){ diff --git a/udp_server.c b/udp_server.c index a54a4fe..d4a9d7b 100644 --- a/udp_server.c +++ b/udp_server.c @@ -41,14 +41,14 @@ * 2007-08-28 disable/set MTU discover option for the udp sockets * (in linux it's enabled by default which produces udp packets * with the DF flag ser) (patch from hscholz) + * 2010-06-15 support for using raw sockets for sending (andrei) */
-/*! - * \file - * \brief SIP-router core :: - * \ingroup core - * Module: \ref core +/** udp send and loop-receive functions. + * @file udp_server.c + * @ingroup core + * Module: @ref core */
#include <stdlib.h> @@ -67,6 +67,7 @@
#include "udp_server.h" +#include "compiler_opt.h" #include "globals.h" #include "config.h" #include "dprint.h" @@ -74,6 +75,10 @@ #include "mem/mem.h" #include "ip_addr.h" #include "cfg/cfg_struct.h" +#ifdef USE_RAW_SOCKS +#include "raw_sock.h" +#endif /* USE_RAW_SOCKS */ +
#ifdef USE_STUN #include "ser_stun.h" @@ -551,6 +556,9 @@ int udp_send(struct dest_info* dst, char *buf, unsigned len) int n; int tolen; struct ip_addr ip; /* used only on error, for debugging */ +#ifdef USE_RAW_SOCKS + int mtu; +#endif /* USE_RAW_SOCKS */
#ifdef DBG_MSG_QA /* aborts on error, does nothing otherwise */ @@ -559,24 +567,47 @@ int udp_send(struct dest_info* dst, char *buf, unsigned len) abort(); } #endif - - tolen=sockaddru_len(dst->to); +#ifdef USE_RAW_SOCKS + if (likely( ! (raw_udp4_send_sock >= 0 && + cfg_get(core, core_cfg, udp4_raw) && + dst->send_sock->address.af == AF_INET) )) { +#endif /* USE_RAW_SOCKS */ + /* normal send over udp socket */ + tolen=sockaddru_len(dst->to); again: - n=sendto(dst->send_sock->socket, buf, len, 0, &dst->to.s, tolen); + n=sendto(dst->send_sock->socket, buf, len, 0, &dst->to.s, tolen); #ifdef XL_DEBUG - LOG(L_INFO, "INFO: send status: %d\n", n); + LOG(L_INFO, "INFO: send status: %d\n", n); #endif - if (n==-1){ - su2ip_addr(&ip, &dst->to); - LOG(L_ERR, "ERROR: udp_send: sendto(sock,%p,%u,0,%s:%d,%d): %s(%d)\n", - buf,len, ip_addr2a(&ip), su_getport(&dst->to), tolen, - strerror(errno),errno); - if (errno==EINTR) goto again; - if (errno==EINVAL) { - LOG(L_CRIT,"CRITICAL: invalid sendtoparameters\n" - "one possible reason is the server is bound to localhost and\n" - "attempts to send to the net\n"); + if (unlikely(n==-1)){ + su2ip_addr(&ip, &dst->to); + LOG(L_ERR, "ERROR: udp_send: sendto(sock,%p,%u,0,%s:%d,%d):" + " %s(%d)\n", buf,len, ip_addr2a(&ip), + su_getport(&dst->to), tolen, strerror(errno), errno); + if (errno==EINTR) goto again; + if (errno==EINVAL) { + LOG(L_CRIT,"CRITICAL: invalid sendtoparameters\n" + "one possible reason is the server is bound to localhost and\n" + "attempts to send to the net\n"); + } + } +#ifdef USE_RAW_SOCKS + } else { + /* send over a raw socket */ + mtu = cfg_get(core, core_cfg, udp4_raw_mtu); +raw_again: + n=raw_iphdr_udp4_send(raw_udp4_send_sock, buf, len, + &dst->send_sock->su, + &dst->to, + mtu); + if (unlikely(n==-1)){ + su2ip_addr(&ip, &dst->to); + LOG(L_ERR, "ERROR: raw_udp4_send(sock,%p,%u,...,%s:%d,%d):" + " %s(%d)\n", buf,len, ip_addr2a(&ip), + su_getport(&dst->to), mtu, strerror(errno), errno); + if (errno==EINTR) goto raw_again; } } +#endif /* USE_RAW_SOCKS */ return n; }
15 jun 2010 kl. 16.45 skrev Andrei Pelinescu-Onciul:
raw sockets: udp send will use now raw sockets if enabled
A raw socket, that will be used for sending, is now initialized on startup. The operation can succeed only if sr is started as root or with CAP_NET_RAW. If the initialization fails and the raw sockets are forced on from the config (udp4_raw = 1), ser won't start. If the raw socket are in auto mode (udp4_raw = -1), sr will start, but with the raw socket send part disabled (normal udp send will be used).
If the raw socket part is not disabled at startup, it can be turned anytime on/off via the runtime cfg. framework.
Note: the raw socket send is supported only over ipv4 and for now only on linux.
Andrei, Can you explain the benefit of the raw sockets too? This sounds very interesting, but I don't see the reason why you want this. I am very curious!
Thanks, /O
On Jun 16, 2010 at 08:41, Olle E. Johansson oej@edvina.net wrote:
15 jun 2010 kl. 16.45 skrev Andrei Pelinescu-Onciul:
raw sockets: udp send will use now raw sockets if enabled
A raw socket, that will be used for sending, is now initialized on startup. The operation can succeed only if sr is started as root or with CAP_NET_RAW. If the initialization fails and the raw sockets are forced on from the config (udp4_raw = 1), ser won't start. If the raw socket are in auto mode (udp4_raw = -1), sr will start, but with the raw socket send part disabled (normal udp send will be used).
If the raw socket part is not disabled at startup, it can be turned anytime on/off via the runtime cfg. framework.
Note: the raw socket send is supported only over ipv4 and for now only on linux.
Andrei, Can you explain the benefit of the raw sockets too? This sounds very interesting, but I don't see the reason why you want this. I am very curious!
It's experimental stuff for now. See http://lists.sip-router.org/pipermail/sr-dev/2010-June/007760.html for a little more info. More details after I get to do some performance testing.
Also parts of the code will be used in the future for icmp based blacklisting and maybe for some kind of udp only transparent proxy or load balancer modules (icmp much more likely to happen though).
Andrei
16 jun 2010 kl. 08.48 skrev Andrei Pelinescu-Onciul:
On Jun 16, 2010 at 08:41, Olle E. Johansson oej@edvina.net wrote:
15 jun 2010 kl. 16.45 skrev Andrei Pelinescu-Onciul:
raw sockets: udp send will use now raw sockets if enabled
A raw socket, that will be used for sending, is now initialized on startup. The operation can succeed only if sr is started as root or with CAP_NET_RAW. If the initialization fails and the raw sockets are forced on from the config (udp4_raw = 1), ser won't start. If the raw socket are in auto mode (udp4_raw = -1), sr will start, but with the raw socket send part disabled (normal udp send will be used).
If the raw socket part is not disabled at startup, it can be turned anytime on/off via the runtime cfg. framework.
Note: the raw socket send is supported only over ipv4 and for now only on linux.
Andrei, Can you explain the benefit of the raw sockets too? This sounds very interesting, but I don't see the reason why you want this. I am very curious!
It's experimental stuff for now. See http://lists.sip-router.org/pipermail/sr-dev/2010-June/007760.html for a little more info. More details after I get to do some performance testing.
Also parts of the code will be used in the future for icmp based blacklisting and maybe for some kind of udp only transparent proxy or load balancer modules (icmp much more likely to happen though).
Ahh. So we will react to ICMP unreachable messages. That's a huge improvement!
Thanks. /O
Andrei Pelinescu-Onciul wrote:
Module: sip-router Branch: andrei/raw_sock Commit: 22e7e32e343724a42abc4c0c1b7986e88e50111b URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=22e7e32e...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@iptel.org Date: Tue Jun 15 16:36:14 2010 +0200
raw sockets: udp send will use now raw sockets if enabled
A raw socket, that will be used for sending, is now initialized on startup. The operation can succeed only if sr is started as root or with CAP_NET_RAW. If the initialization fails and the raw sockets are forced on from the config (udp4_raw = 1), ser won't start. If the raw socket are in auto mode (udp4_raw = -1), sr will start, but with the raw socket send part disabled (normal udp send will be used).
If the raw socket part is not disabled at startup, it can be turned anytime on/off via the runtime cfg. framework.
Note: the raw socket send is supported only over ipv4 and for now only on linux.
Hello,
Good to see that the last bits are in order. I will start with performance testing a.s.a.p
Marius
On Jun 16, 2010 at 14:21, marius zbihlei marius.zbihlei@1and1.ro wrote:
Andrei Pelinescu-Onciul wrote:
Module: sip-router Branch: andrei/raw_sock Commit: 22e7e32e343724a42abc4c0c1b7986e88e50111b URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=22e7e32e...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@iptel.org Date: Tue Jun 15 16:36:14 2010 +0200
raw sockets: udp send will use now raw sockets if enabled
A raw socket, that will be used for sending, is now initialized on startup. The operation can succeed only if sr is started as root or with CAP_NET_RAW. If the initialization fails and the raw sockets are forced on from the config (udp4_raw = 1), ser won't start. If the raw socket are in auto mode (udp4_raw = -1), sr will start, but with the raw socket send part disabled (normal udp send will be used).
If the raw socket part is not disabled at startup, it can be turned anytime on/off via the runtime cfg. framework.
Note: the raw socket send is supported only over ipv4 and for now only on linux.
Hello,
Good to see that the last bits are in order. I will start with performance testing a.s.a.p
Great, you need: git checkout -b raw_socks origin/andrei/socks make config extra_defs=-DUSE_RAW_SOCKS
and in .cfg: udp4_raw=1 # or -1 udp4_mtu=... (if you have a lower mut then 1500)
I probably won't be able to do any performance testing this week.
Andrei