|
@@ -0,0 +1,147 @@
|
|
|
+/*
|
|
|
+ * Copyright (C) 2010 iptelorg GmbH
|
|
|
+ *
|
|
|
+ * Permission to use, copy, modify, and distribute this software for any
|
|
|
+ * purpose with or without fee is hereby granted, provided that the above
|
|
|
+ * copyright notice and this permission notice appear in all copies.
|
|
|
+ *
|
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
+ */
|
|
|
+/** raw socket udp listen functions.
|
|
|
+ * @file raw_listener.c
|
|
|
+ * @ingroup core
|
|
|
+ * Module: @ref core
|
|
|
+ */
|
|
|
+/*
|
|
|
+ * History:
|
|
|
+ * --------
|
|
|
+ * 2010-06-09 intial version (from older code) andrei
|
|
|
+ */
|
|
|
+
|
|
|
+#ifdef USE_RAW_SOCKS
|
|
|
+
|
|
|
+#include "../../config.h"
|
|
|
+#include "../../receive.h"
|
|
|
+
|
|
|
+#include "raw_listener.h"
|
|
|
+#include "raw_sock.h"
|
|
|
+#include "tlb_send.h"
|
|
|
+#include "tlb_cfg.h"
|
|
|
+
|
|
|
+#include <errno.h>
|
|
|
+#include <string.h>
|
|
|
+
|
|
|
+struct raw_listen_info* raw_sendipv4=0;
|
|
|
+
|
|
|
+/** creates a raw socket based on a socket_info structure.
|
|
|
+ * Side-effects: sets raw_udp_sendipv4 if not already set.
|
|
|
+ * @param si - pointer to partially filled socket_info structure (su must
|
|
|
+ * be set).
|
|
|
+ * @param iface - pointer to network interface to bind on (str). Can be null.
|
|
|
+ * @param iphdr_incl - 1 if send on these socket will include the IP header.
|
|
|
+ * @return <0 on error, socket on success.
|
|
|
+ */
|
|
|
+int raw_listener_init(struct socket_info* si, str* iface, int iphdr_incl)
|
|
|
+{
|
|
|
+ int sock;
|
|
|
+ struct ip_addr ip;
|
|
|
+
|
|
|
+ su2ip_addr(&ip, &si->su);
|
|
|
+ sock=raw_udp4_socket(&ip, iface, iphdr_incl);
|
|
|
+ if (sock>=0){
|
|
|
+ if (raw_sendipv4==0 || iface==0 || iface->s==0)
|
|
|
+ raw_udp_sendipv4=si;
|
|
|
+ }
|
|
|
+ return sock;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/** receive sip udp ipv4 packets over a raw socket in a loop.
|
|
|
+ * It should be called by a "raw socket receiver" process
|
|
|
+ * (since the function never exits unless it encounters a
|
|
|
+ * critical error).
|
|
|
+ * @param rsock - initialized raw socket.
|
|
|
+ * @param port1 - start of port range.
|
|
|
+ * @param port2 - end of port range. If 0 it's equivalent to listening only
|
|
|
+ * on port1.
|
|
|
+ * @return <0 on error, never returns on success.
|
|
|
+ */
|
|
|
+int raw_udp4_rcv_loop(int rsock, int port1, int port2)
|
|
|
+{
|
|
|
+ static char buf[BUF_SIZE+1];
|
|
|
+ char* p;
|
|
|
+ char* tmp;
|
|
|
+ union sockaddr_union from;
|
|
|
+ union sockaddr_union to;
|
|
|
+ struct receive_info ri;
|
|
|
+ struct raw_filter rf;
|
|
|
+ int len;
|
|
|
+
|
|
|
+ /* this will not change */
|
|
|
+ from.sin.sin_family=AF_INET;
|
|
|
+ ri.bind_address=0;
|
|
|
+ ri.proto=PROTO_UDP;
|
|
|
+ ri.proto_reserved1=0;
|
|
|
+ ri.proto_reserved2=0;
|
|
|
+ /* set filter to match any address but with the specified port range */
|
|
|
+ memset(&rf, 0, sizeof(rf));
|
|
|
+ rf.dst.ip.af=AF_INET;
|
|
|
+ rf.dst.ip.len=4;
|
|
|
+ rf.dst.mask.af=AF_INET;
|
|
|
+ rf.dst.mask.len=4;
|
|
|
+ rf.proto=PROTO_UDP;
|
|
|
+ rf.port1=port1;
|
|
|
+ rf.port2=port2?port2:port1;
|
|
|
+ for(;;){
|
|
|
+ p=buf;
|
|
|
+ len=raw_udp4_recv(rsock, &p, BUF_SIZE, &from, &to, &rf);
|
|
|
+ if (len<0){
|
|
|
+ if (len==-1){
|
|
|
+ LOG(L_ERR, "ERROR: raw_udp4_rcv_loop:raw_udp4_recv: %s [%d]\n",
|
|
|
+ strerror(errno), errno);
|
|
|
+ if ((errno==EINTR)||(errno==EWOULDBLOCK))
|
|
|
+ continue;
|
|
|
+ else
|
|
|
+ goto error;
|
|
|
+ }else{
|
|
|
+ DBG("raw_udp4_rcv_loop: raw_udp4_recv error: %d\n", len);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* we must 0-term the message */
|
|
|
+ p[len]=0;
|
|
|
+ ri.src_su=from;
|
|
|
+ su2ip_addr(&ri.src_ip, &from);
|
|
|
+ ri.src_port=su_getport(&from);
|
|
|
+ su2ip_addr(&ri.dst_ip, &to);
|
|
|
+ ri.dst_port=su_getport(&to);
|
|
|
+ /* sanity checks */
|
|
|
+ if (len<MIN_UDP_PACKET){
|
|
|
+ tmp=ip_addr2a(&ri.src_ip);
|
|
|
+ DBG("raw_udp4_rcv_loop: probing packet received from %s %d\n",
|
|
|
+ tmp, htons(ri.src_port));
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (ri.src_port==0){
|
|
|
+ tmp=ip_addr2a(&ri.src_ip);
|
|
|
+ LOG(L_INFO, "raw_udp4_rcv_loop: dropping 0 port packet from %s\n",
|
|
|
+ tmp);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ tmp=ip_addr2a(&ri.src_ip);
|
|
|
+ DBG("raw_udp4_rcv_loop: received from %s:\n[%.*s]\n", tmp, len, p);
|
|
|
+ receive_msg(p, len, &ri);
|
|
|
+ }
|
|
|
+error:
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+#endif /* USE_RAW_SOCKS */
|