Browse Source

modules:sipcapture: IPIP raw socket has moved to the sipcapture.
fixed source(from) structure in IPIP mode
fixed port and port range in monitoring/ipip mode.

Alexandr Dubovikov 14 years ago
parent
commit
8c9681ac3b
3 changed files with 112 additions and 52 deletions
  1. 20 10
      modules/sipcapture/README
  2. 16 4
      modules/sipcapture/doc/sipcapture_admin.xml
  3. 76 38
      modules/sipcapture/sipcapture.c

+ 20 - 10
modules/sipcapture/README

@@ -25,7 +25,7 @@ Alexandr Dubovikov
               2.1. Kamailio Modules
               2.1. Kamailio Modules
               2.2. External Libraries or Applications
               2.2. External Libraries or Applications
 
 
-        3. Exported Parameters
+        3. Parameters
 
 
               3.1. db_url (str)
               3.1. db_url (str)
               3.2. table_name (str)
               3.2. table_name (str)
@@ -42,7 +42,7 @@ Alexandr Dubovikov
               3.13. raw_moni_bpf_on (integer)
               3.13. raw_moni_bpf_on (integer)
               3.14. capture_node (str)
               3.14. capture_node (str)
 
 
-        4. Exported MI Functions
+        4. MI Commands
 
 
               4.1. sip_capture
               4.1. sip_capture
 
 
@@ -76,7 +76,7 @@ Chapter 1. Admin Guide
         2.1. Kamailio Modules
         2.1. Kamailio Modules
         2.2. External Libraries or Applications
         2.2. External Libraries or Applications
 
 
-   3. Exported Parameters
+   3. Parameters
 
 
         3.1. db_url (str)
         3.1. db_url (str)
         3.2. table_name (str)
         3.2. table_name (str)
@@ -93,7 +93,7 @@ Chapter 1. Admin Guide
         3.13. raw_moni_bpf_on (integer)
         3.13. raw_moni_bpf_on (integer)
         3.14. capture_node (str)
         3.14. capture_node (str)
 
 
-   4. Exported MI Functions
+   4. MI Commands
 
 
         4.1. sip_capture
         4.1. sip_capture
 
 
@@ -132,7 +132,7 @@ Chapter 1. Admin Guide
    running Kamailio with this module loaded:
    running Kamailio with this module loaded:
      * None.
      * None.
 
 
-3. Exported Parameters
+3. Parameters
 
 
    3.1. db_url (str)
    3.1. db_url (str)
    3.2. table_name (str)
    3.2. table_name (str)
@@ -243,9 +243,19 @@ modparam("sipcapture", "raw_moni_capture_on", 1)
 
 
 3.9. raw_socket_listen (string)
 3.9. raw_socket_listen (string)
 
 
-   Parameter indicate an listen IP address of RAW socket. You can also
-   define a port or portrange, which make sense only in
-   monitoring/mirroring capture mode.
+   Parameter indicate an listen IP address of RAW socket for IPIP
+   capturing. You can also define a port/portrange for IPIP/Mirroring
+   mode, to capture SIP messages in specific ports:
+
+   "10.0.0.1:5060" - the source/destination port of the SIP message must
+   be equal 5060
+
+   "10.0.0.1:5060-5090" - the source/destination port of the SIP message
+   must be equal or be between 5060 and 5090.
+
+   The port/portrange must be defined if you are planning to use mirroring
+   capture! In this case, the part with IP address will be ignored, but to
+   make parser happy, use i.e. 10.0.0.0
 
 
    Default value is "".
    Default value is "".
 
 
@@ -295,7 +305,7 @@ modparam("sipcapture", "promiscuous_on", 1)
 
 
    Activate Linux Socket Filter (LSF based on BPF) on the mirroring
    Activate Linux Socket Filter (LSF based on BPF) on the mirroring
    interface. The structure is defined in linux/filter.h. The default LSF
    interface. The structure is defined in linux/filter.h. The default LSF
-   accept a portrange from the raw_socket_listen param. Currently LSF
+   accept a port/portrange from the raw_socket_listen param. Currently LSF
    supported only on Linux.
    supported only on Linux.
 
 
    Default value is "0".
    Default value is "0".
@@ -316,7 +326,7 @@ modparam("sipcapture", "raw_moni_bpf_on", 1)
 modparam("sipcapture", "capture_node", "homer03")
 modparam("sipcapture", "capture_node", "homer03")
 ...
 ...
 
 
-4. Exported MI Functions
+4. MI Commands
 
 
    4.1. sip_capture
    4.1. sip_capture
 
 

+ 16 - 4
modules/sipcapture/doc/sipcapture_admin.xml

@@ -238,9 +238,21 @@ modparam("sipcapture", "raw_moni_capture_on", 1)
 	<section>
 	<section>
                 <title><varname>raw_socket_listen</varname> (string)</title>
                 <title><varname>raw_socket_listen</varname> (string)</title>
                 <para>
                 <para>
-                Parameter indicate an listen IP address of RAW socket. You can also define
-		a port or portrange, which make sense only in monitoring/mirroring 
-		capture mode. 
+                Parameter indicate an listen IP address of RAW socket for IPIP capturing. 
+                You can also define a port/portrange for IPIP/Mirroring mode, to capture 
+                SIP messages in specific ports:
+		<para>
+		"10.0.0.1:5060" - the source/destination port of the SIP message must be equal 5060
+		</para>
+		<para>
+		"10.0.0.1:5060-5090" - the source/destination port of the SIP message must be 
+		equal or be between 5060 and 5090.
+		</para>
+		<para>
+		The port/portrange must be defined if you are planning to
+		use mirroring capture! In this case, the part with IP address will be
+                ignored, but to make parser happy, use i.e. 10.0.0.0
+		</para>
                 </para>
                 </para>
                 <para>
                 <para>
                 <emphasis>
                 <emphasis>
@@ -320,7 +332,7 @@ modparam("sipcapture", "promiscuous_on", 1)
                 <title><varname>raw_moni_bpf_on</varname> (integer)</title>
                 <title><varname>raw_moni_bpf_on</varname> (integer)</title>
                 <para>
                 <para>
                 Activate Linux Socket Filter (LSF based on BPF) on the mirroring interface. 
                 Activate Linux Socket Filter (LSF based on BPF) on the mirroring interface. 
-                The structure is defined in linux/filter.h. The default LSF accept a portrange
+                The structure is defined in linux/filter.h. The default LSF accept a port/portrange
                 from the raw_socket_listen param. Currently LSF supported only on Linux.
                 from the raw_socket_listen param. Currently LSF supported only on Linux.
                 </para>
                 </para>
                 <para>
                 <para>

+ 76 - 38
modules/sipcapture/sipcapture.c

@@ -71,8 +71,6 @@
 #include "../../pvar.h"
 #include "../../pvar.h"
 #include "../../str.h"
 #include "../../str.h"
 #include "../../onsend.h"
 #include "../../onsend.h"
-#include "../../raw_sock.h"
-#include "../../raw_listener.h"
 #include "../../resolve.h"
 #include "../../resolve.h"
 #include "../../receive.h"
 #include "../../receive.h"
 #include "sipcapture.h"
 #include "sipcapture.h"
@@ -141,8 +139,8 @@ static int sip_capture(struct sip_msg *msg, char *s1, char *s2);
 int hep_msg_received(void *data);
 int hep_msg_received(void *data);
 int init_rawsock_children(void);
 int init_rawsock_children(void);
 int extract_host_port(void);
 int extract_host_port(void);
-int raw_moni_socket(str* iface, int port_start, int port_end);
-int raw_moni_rcv_loop(int rsock, int port1, int port2);
+int raw_capture_socket(struct ip_addr* ip, str* iface, int port_start, int port_end, int proto);
+int raw_capture_rcv_loop(int rsock, int port1, int port2, int ipip);
 
 
 
 
 
 
@@ -197,7 +195,7 @@ int capture_on   = 0;
 int hep_capture_on   = 0;
 int hep_capture_on   = 0;
 int ipip_capture_on   = 0;
 int ipip_capture_on   = 0;
 int moni_capture_on   = 0;
 int moni_capture_on   = 0;
-int moni_port_start = 5060;
+int moni_port_start = 0;
 int moni_port_end   = 0;
 int moni_port_end   = 0;
 int *capture_on_flag = NULL;
 int *capture_on_flag = NULL;
 int db_insert_mode = 0;
 int db_insert_mode = 0;
@@ -443,7 +441,9 @@ static int mod_init(void) {
 	if(ipip_capture_on && moni_capture_on) {
 	if(ipip_capture_on && moni_capture_on) {
 		LM_ERR("ERROR:sipcapture:mod_init: only one RAW mode is supported. Please disable ipip_capture_on or moni_capture_on\n");
 		LM_ERR("ERROR:sipcapture:mod_init: only one RAW mode is supported. Please disable ipip_capture_on or moni_capture_on\n");
 		return -1;		                		
 		return -1;		                		
-	}		
+	}
+	
+
 
 
 	/* raw processes for IPIP encapsulation */
 	/* raw processes for IPIP encapsulation */
 	if (ipip_capture_on || moni_capture_on) {
 	if (ipip_capture_on || moni_capture_on) {
@@ -459,10 +459,14 @@ static int mod_init(void) {
 			return -1;
 			return -1;
 		}		
 		}		
 			
 			
-		raw_sock_desc = ipip_capture_on ? raw_socket( IPPROTO_IPIP, raw_socket_listen.len ? ip : 0, 
-						raw_interface.len ? &raw_interface : 0, 0) : 
-						 raw_moni_socket(raw_interface.len ? &raw_interface : 0, 
-						         moni_port_start, moni_port_end ? moni_port_end : moni_port_start);				
+        	if(moni_capture_on && !moni_port_start) {
+	        	LM_ERR("ERROR:sipcapture:mod_init: Please define port/portrange in 'raw_socket_listen', before \
+	        	                        activate monitoring capture\n");
+        		return -1;		                		
+                }			
+			
+		raw_sock_desc = raw_capture_socket(raw_socket_listen.len ? ip : 0, raw_interface.len ? &raw_interface : 0, 
+		                                moni_port_start, moni_port_end , ipip_capture_on ? IPPROTO_IPIP : htons(0x0800));						         
 						
 						
 		if(raw_sock_desc < 0) {
 		if(raw_sock_desc < 0) {
 			LM_ERR("could not initialize raw udp socket:"
 			LM_ERR("could not initialize raw udp socket:"
@@ -475,8 +479,6 @@ static int mod_init(void) {
 			return -1;		
 			return -1;		
 		}
 		}
 
 
-		if(ipip_capture_on) raw_ipip = 1; /* IPIP mode for raw socket */
-
 		if(promisc_on && raw_interface.len) {
 		if(promisc_on && raw_interface.len) {
 
 
 			 memset(&ifr, 0, sizeof(ifr));
 			 memset(&ifr, 0, sizeof(ifr));
@@ -567,10 +569,7 @@ int init_rawsock_children(void)
                         ERR("Unable to fork: %s\n", strerror(errno));
                         ERR("Unable to fork: %s\n", strerror(errno));
                         return -1;
                         return -1;
                 } else if (pid == 0) { /* child */
                 } else if (pid == 0) { /* child */
-			if(moni_capture_on) 
-				raw_moni_rcv_loop(raw_sock_desc, moni_port_start, moni_port_end);
-			else 
-				raw_udp4_rcv_loop(raw_sock_desc, 0, 0); 
+			raw_capture_rcv_loop(raw_sock_desc, moni_port_start, moni_port_end, moni_capture_on ? 0 : 1);
                 }
                 }
                 /* Parent */
                 /* Parent */
         }
         }
@@ -962,7 +961,7 @@ static int sip_capture_store(struct _sipcapture_object *sco)
 	db_vals[36].nul = 0;
 	db_vals[36].nul = 0;
 	db_vals[36].val.blob_val = sco->msg;	
 	db_vals[36].val.blob_val = sco->msg;	
 		
 		
-	DBG("TABLE =====================: [%.*s]\n", table_name.len, table_name.s);		
+	DBG("homer table: [%.*s]\n", table_name.len, table_name.s);		
 	if(!partitioning_mode) {
 	if(!partitioning_mode) {
                 ret = snprintf(tmptable, TABLE_LEN, "%.*s_%02d_%02d",
                 ret = snprintf(tmptable, TABLE_LEN, "%.*s_%02d_%02d",
                         table_name.len, table_name.s, (t->tm_wday == 0) ? 7 : t->tm_wday , t->tm_hour);
                         table_name.len, table_name.s, (t->tm_wday == 0) ? 7 : t->tm_wday , t->tm_hour);
@@ -1317,23 +1316,38 @@ static struct mi_root* sip_capture_mi(struct mi_root* cmd_tree, void* param )
 	}
 	}
 }
 }
 
 
-int raw_moni_socket(str* iface, int port_start, int port_end)
+/* Local raw socket */
+int raw_capture_socket(struct ip_addr* ip, str* iface, int port_start, int port_end, int proto)
 {
 {
 
 
-	int sock;	
-	
+	int sock = -1;	
+	union sockaddr_union su;
+
 #ifdef __OS_linux
 #ifdef __OS_linux
 	struct sock_fprog pf;
 	struct sock_fprog pf;
 	char short_ifname[sizeof(int)];
 	char short_ifname[sizeof(int)];
 	int ifname_len;
 	int ifname_len;
 	char* ifname;
 	char* ifname;
- 
+#endif 
  	//0x0003 - all packets
  	//0x0003 - all packets
-	sock = socket(PF_PACKET, SOCK_RAW, htons(0x0800));
-
+ 	if(proto == IPPROTO_IPIP) {
+        	sock = socket(PF_INET, SOCK_RAW, proto);
+        }
+#ifdef __OS_linux
+ 	else if(proto == htons(0x800)) {
+        	sock = socket(PF_PACKET, SOCK_RAW, proto);
+        }
+#endif
+        else {
+                ERR("raw_capture_socket: LSF currently suppoted only on linux\n");
+                goto error;                        
+        }
+                
 	if (sock==-1)
 	if (sock==-1)
 		goto error;
 		goto error;
 
 
+#ifdef __OS_linux
+
 	/* set socket options */
 	/* set socket options */
 	if (iface && iface->s){
 	if (iface && iface->s){
 
 
@@ -1361,6 +1375,8 @@ int raw_moni_socket(str* iface, int port_start, int port_end)
 	        pf.len = sizeof(BPF_code) / sizeof(BPF_code[0]);
 	        pf.len = sizeof(BPF_code) / sizeof(BPF_code[0]);
         	pf.filter = (struct sock_filter *) BPF_code;
         	pf.filter = (struct sock_filter *) BPF_code;
 
 
+                if(!port_end) port_end = port_start;
+                
         	/* Start PORT */
         	/* Start PORT */
         	BPF_code[5]  = (struct sock_filter)BPF_JUMP(0x35, port_start, 0, 1);
         	BPF_code[5]  = (struct sock_filter)BPF_JUMP(0x35, port_start, 0, 1);
         	BPF_code[8] = (struct  sock_filter)BPF_JUMP(0x35, port_start, 11, 13);
         	BPF_code[8] = (struct  sock_filter)BPF_JUMP(0x35, port_start, 11, 13);
@@ -1375,15 +1391,18 @@ int raw_moni_socket(str* iface, int port_start, int port_end)
         	if(setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf)) < 0 ) {
         	if(setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf)) < 0 ) {
                         ERR(" setsockopt filter: [%s] [%d]\n", strerror(errno), errno);
                         ERR(" setsockopt filter: [%s] [%d]\n", strerror(errno), errno);
                 }		
                 }		
-
-
         }
         }
-
-#else
-        ERR("raw_moni_socket: currently suppoted only on linux\n");
-        goto error;
 #endif
 #endif
 
 
+        if (ip && proto == IPPROTO_IPIP){
+                init_su(&su, ip, 0);
+                if (bind(sock, &su.s, sockaddru_len(su))==-1){
+                        ERR("raw_capture_socket: bind(%s) failed: %s [%d]\n",
+                                ip_addr2a(ip), strerror(errno), errno);
+                        goto error;
+                }
+        }
+
 	return sock;
 	return sock;
 	
 	
 error:
 error:
@@ -1392,7 +1411,8 @@ error:
                		
                		
 }
 }
 
 
-int raw_moni_rcv_loop(int rsock, int port1, int port2) {
+/* Local raw receive loop */
+int raw_capture_rcv_loop(int rsock, int port1, int port2, int ipip) {
 
 
 
 
 	static char buf [BUF_SIZE+1];
 	static char buf [BUF_SIZE+1];
@@ -1402,6 +1422,8 @@ int raw_moni_rcv_loop(int rsock, int port1, int port2) {
 	int len;
 	int len;
 	struct ip *iph;
 	struct ip *iph;
         struct udphdr *udph;
         struct udphdr *udph;
+        char* udph_start;
+        unsigned short udp_len;
 	int offset = 0; 
 	int offset = 0; 
 	char* end;
 	char* end;
 	unsigned short dst_port;
 	unsigned short dst_port;
@@ -1426,24 +1448,35 @@ int raw_moni_rcv_loop(int rsock, int port1, int port2) {
 
 
 		end=buf+len;
 		end=buf+len;
 		
 		
+		offset =  ipip ? sizeof(struct ip) : ETHHDR;
 		
 		
-		if (unlikely(len<(sizeof(struct ip)+sizeof(struct udphdr) + ETHHDR))) {
-			LOG(L_ERR, "ERROR: small packet: %d\n",len);
+		if (unlikely(len<(sizeof(struct ip)+sizeof(struct udphdr) + offset))) {
+			DBG("received small packet: %d. Ignore it\n",len);
                 	continue;
                 	continue;
         	}
         	}
-
-        	offset = ETHHDR;
 		
 		
 		iph = (struct ip*) (buf + offset);				
 		iph = (struct ip*) (buf + offset);				
+
 		offset+=iph->ip_hl*4;
 		offset+=iph->ip_hl*4;
+
+		udph_start = buf+offset;
 		
 		
-		udph = (struct udphdr*)(buf + offset);
+		udph = (struct udphdr*) udph_start;
 		offset +=sizeof(struct udphdr);
 		offset +=sizeof(struct udphdr);
 
 
         	if (unlikely((buf+offset)>end)){
         	if (unlikely((buf+offset)>end)){
-                	continue;
-	                
+                	continue;	                
         	}
         	}
+
+		udp_len=ntohs(udph->uh_ulen);
+	        if (unlikely((udph_start+udp_len)!=end)){
+        	        if ((udph_start+udp_len)>end){
+				continue;
+        	        }else{
+                	        DBG("udp length too small: %d/%d\n", (int)udp_len, (int)(end-udph_start));
+	                        continue;
+        	        }
+	        }
         									
         									
 		/*FIL IPs*/
 		/*FIL IPs*/
 		dst_ip.af=AF_INET;
 		dst_ip.af=AF_INET;
@@ -1465,6 +1498,7 @@ int raw_moni_rcv_loop(int rsock, int port1, int port2) {
                 ri.src_port=src_port;
                 ri.src_port=src_port;
                 su2ip_addr(&ri.dst_ip, &to);
                 su2ip_addr(&ri.dst_ip, &to);
                 ri.dst_port=dst_port;
                 ri.dst_port=dst_port;
+                ri.proto=PROTO_UDP;                                
 
 
 		/* cut off the offset */
 		/* cut off the offset */
 	        len -= offset;
 	        len -= offset;
@@ -1474,7 +1508,11 @@ int raw_moni_rcv_loop(int rsock, int port1, int port2) {
                         continue;
                         continue;
                 }
                 }
 
 
-		if((src_port >= port1 && src_port <= port2) || (dst_port >= port1 && dst_port <= port2))
+                DBG("PORT: [%d] and [%d]\n", port1, port2);
+                
+		if((!port1 && !port2) 
+		        || (src_port >= port1 && src_port <= port2) || (dst_port >= port1 && dst_port <= port2) 
+		        || (!port2 && (src_port == port1 || dst_port == port1)))
 		                          receive_msg(buf+offset, len, &ri);
 		                          receive_msg(buf+offset, len, &ri);
 	}
 	}