pkg/kamailio/fedora/16: Updated rel in .spec to dev2
[sip-router] / raw_listener.c
1 /*
2  * Copyright (C) 2010 iptelorg GmbH
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 /** raw socket udp listen functions.
17  *  @file raw_listener.c
18  *  @ingroup core
19  *  Module: @ref core
20  */
21 /*
22  * History:
23  * --------
24  *  2010-06-09  intial version (from older code) andrei
25  */
26
27 #ifdef USE_RAW_SOCKS
28
29
30 #include "raw_listener.h"
31 #include "raw_sock.h"
32 #include "receive.h"
33
34 #include <errno.h>
35 #include <string.h>
36
37 struct socket_info* raw_udp_sendipv4=0;
38
39 /** creates a raw socket based on a socket_info structure.
40  * Side-effects: sets raw_udp_sendipv4 if not already set.
41  * @param si - pointer to partially filled socket_info structure (su must
42  *              be set).
43  * @param iface - pointer to network interface to bind on (str). Can be null.
44  * @param iphdr_incl - 1 if send on these socket will include the IP header.
45  * @return <0 on error, socket on success.
46  */
47 int raw_listener_init(struct socket_info* si, str* iface, int iphdr_incl)
48 {
49         int sock;
50         struct ip_addr ip;
51         
52         su2ip_addr(&ip, &si->su);
53         sock=raw_udp4_socket(&ip, iface, iphdr_incl);
54         if (sock>=0){
55                 if (raw_udp_sendipv4==0 || iface==0 || iface->s==0)
56                         raw_udp_sendipv4=si;
57         }
58         return sock;
59 }
60
61
62
63 /** receive sip udp ipv4 packets over a raw socket in a loop.
64  * It should be called by a "raw socket receiver" process
65  * (since the function never exits unless it encounters a
66  *  critical error).
67  * @param rsock - initialized raw socket.
68  * @param port1 - start of port range.
69  * @param port2 - end of port range. If 0 it's equivalent to listening only
70  *                on port1.
71  * @return <0 on error, never returns on success.
72  */
73 int raw_udp4_rcv_loop(int rsock, int port1, int port2)
74 {
75         static char buf[BUF_SIZE+1];
76         char* p;
77         char* tmp;
78         union sockaddr_union from;
79         union sockaddr_union to;
80         struct receive_info ri;
81         struct raw_filter rf;
82         int len;
83         
84         /* this will not change */
85         from.sin.sin_family=AF_INET;
86         ri.bind_address=0;
87         ri.proto=PROTO_UDP;
88         ri.proto_reserved1=0;
89         ri.proto_reserved2=0;
90         /* set filter to match any address but with the specified port range */
91         memset(&rf, 0, sizeof(rf));
92         rf.dst.ip.af=AF_INET;
93         rf.dst.ip.len=4;
94         rf.dst.mask.af=AF_INET;
95         rf.dst.mask.len=4;
96         rf.proto=PROTO_UDP;
97         rf.port1=port1;
98         rf.port2=port2?port2:port1;
99         for(;;){
100                 p=buf;
101                 len=raw_udp4_recv(rsock, &p, BUF_SIZE, &from, &to, &rf);
102                 if (len<0){
103                         if (len==-1){
104                                 LOG(L_ERR, "ERROR: raw_udp4_rcv_loop:raw_udp4_recv: %s [%d]\n",
105                                                 strerror(errno), errno);
106                                 if ((errno==EINTR)||(errno==EWOULDBLOCK))
107                                         continue;
108                                 else
109                                         goto error;
110                         }else{
111                                 DBG("raw_udp4_rcv_loop: raw_udp4_recv error: %d\n", len);
112                                 continue;
113                         }
114                 }
115                 /* we must 0-term the message */
116                 p[len]=0;
117                 ri.src_su=from;
118                 su2ip_addr(&ri.src_ip, &from);
119                 ri.src_port=su_getport(&from);
120                 su2ip_addr(&ri.dst_ip, &to);
121                 ri.dst_port=su_getport(&to);
122                 /* sanity checks */
123                 if (len<MIN_UDP_PACKET){
124                         tmp=ip_addr2a(&ri.src_ip);
125                         DBG("raw_udp4_rcv_loop: probing packet received from %s %d\n",
126                                         tmp, htons(ri.src_port));
127                         continue;
128                 }
129                 if (ri.src_port==0){
130                         tmp=ip_addr2a(&ri.src_ip);
131                         LOG(L_INFO, "raw_udp4_rcv_loop: dropping 0 port packet from %s\n",
132                                                 tmp);
133                         continue;
134                 }
135                 tmp=ip_addr2a(&ri.src_ip);
136                 DBG("raw_udp4_rcv_loop: received from %s:\n[%.*s]\n", tmp, len, p);
137                 receive_msg(p, len, &ri);
138         }
139 error:
140         return -1;
141 }
142
143
144 #endif /* USE_RAW_SOCKS */