core: Changed WS from being a flag on a TCP/TLS connection to a protocol in its own...
[sip-router] / udp_server.c
index 11d6635..3889a65 100644 (file)
  *  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)
  */
 
 
+/** udp send and loop-receive functions.
+ * @file udp_server.c
+ * @ingroup core
+ * Module: @ref core
+ */
+
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
@@ -60,6 +67,7 @@
 
 
 #include "udp_server.h"
+#include "compiler_opt.h"
 #include "globals.h"
 #include "config.h"
 #include "dprint.h"
 #include "mem/mem.h"
 #include "ip_addr.h"
 #include "cfg/cfg_struct.h"
+#include "events.h"
+#ifdef USE_RAW_SOCKS
+#include "raw_sock.h"
+#endif /* USE_RAW_SOCKS */
+
 
 #ifdef USE_STUN
   #include "ser_stun.h"
@@ -463,6 +476,17 @@ int udp_rcv_loop()
                su2ip_addr(&ri.src_ip, from);
                ri.src_port=su_getport(from);
 
+               if(unlikely(sr_event_enabled(SREV_NET_DGRAM_IN)))
+               {
+                       void *sredp[3];
+                       sredp[0] = (void*)buf;
+                       sredp[1] = (void*)(&len);
+                       sredp[2] = (void*)(&ri);
+                       if(sr_event_exec(SREV_NET_DGRAM_IN, (void*)sredp)<0) {
+                               /* data handled by callback - continue to next packet */
+                               continue;
+                       }
+               }
 #ifndef NO_ZERO_CHECKS
 #ifdef USE_STUN
                /* STUN support can be switched off even if it's compiled */
@@ -544,6 +568,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 */
@@ -552,24 +579,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,%d,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_iphdr_udp4_send(%d,%p,%u,...,%s:%d,%d):"
+                                       " %s(%d)\n", raw_udp4_send_sock, 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;
 }