Browse Source

modules:sipcapture: fixed mirroring capture mode. Currently it works only on Linux.

Alexandr Dubovikov 14 years ago
parent
commit
b7ed9c1e4f

+ 8 - 6
modules/sipcapture/README

@@ -231,7 +231,8 @@ modparam("sipcapture", "raw_ipip_capture_on", 1)
 3.8. raw_moni_capture_on (integer)
 
    Parameter to enable/disable monitoring/mirroring port capturing
-   (on(1)/off(0)) Only one mode on raw socket can be enabled!
+   (on(1)/off(0)) Only one mode on raw socket can be enabled! Monitoring
+   port capturing currently supported only on Linux.
 
    Default value is "0".
 
@@ -292,9 +293,10 @@ modparam("sipcapture", "promiscuous_on", 1)
 
 3.13. raw_moni_bpf_on (integer)
 
-   Activate BPF on the mirroring interface. The structure is defined in
-   sipcapture.h. The default BPF accept a portrange from the
-   raw_socket_listen param.
+   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 from the raw_socket_listen param. Currently LSF
+   supported only on Linux.
 
    Default value is "0".
 
@@ -353,5 +355,5 @@ modparam("sipcapture", "capture_node", "homer03")
    monitoring/mirroring port. Don't activate both at the same time. 2. By
    default MySQL doesn't support INSERT DELAYED for partitioning table.
    You can patch MySQL (http://bugs.mysql.com/bug.php?id=50393) or use
-   separate tables (pseudo partitioning) 3. Promiscuous mode works only on
-   Linux.
+   separate tables (pseudo partitioning) 3. Mirroring port capturing works
+   only on Linux.

+ 6 - 5
modules/sipcapture/doc/sipcapture_admin.xml

@@ -218,7 +218,8 @@ modparam("sipcapture", "raw_ipip_capture_on", 1)
                 <title><varname>raw_moni_capture_on</varname> (integer)</title>
                 <para>
                 Parameter to enable/disable monitoring/mirroring port capturing (on(1)/off(0))
-		Only one mode on raw socket can be enabled!
+		Only one mode on raw socket can be enabled! Monitoring port capturing currently 
+		supported only on Linux.
                 </para>
                 <para>
                 <emphasis>
@@ -318,9 +319,9 @@ modparam("sipcapture", "promiscuous_on", 1)
         <section>
                 <title><varname>raw_moni_bpf_on</varname> (integer)</title>
                 <para>
-                Activate BPF on the mirroring interface. The structure is
-                defined in sipcapture.h. The default BPF accept a portrange
-                from the raw_socket_listen param.
+                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
+                from the raw_socket_listen param. Currently LSF supported only on Linux.
                 </para>
                 <para>
                 <emphasis>
@@ -415,7 +416,7 @@ modparam("sipcapture", "capture_node", "homer03")
 		   Don't activate both at the same time.
 		2. By default MySQL doesn't support INSERT DELAYED for partitioning table. You can patch MySQL 
 		  (http://bugs.mysql.com/bug.php?id=50393) or use separate tables (pseudo partitioning)
-		3. Promiscuous mode works only on Linux.
+		3. Mirroring port capturing works only on Linux.
 	
         </para>
         </section>

+ 3 - 4
modules/sipcapture/examples/kamailio.cfg

@@ -40,20 +40,19 @@ modparam("sipcapture", "hep_capture_on", 1)
 modparam("sipcapture", "raw_interface", "eth0")
 /* activate IPIP capturing */
 modparam("sipcapture", "raw_ipip_capture_on", 1)
-/* activate monitoring/mirroring port capturing */
-modparam("sipcapture", "raw_moni_capture_on", 0)
 /* My table name*/
 modparam("sipcapture", "table_name", "sip_capture")
 /* children for raw socket */
 modparam("sipcapture", "raw_sock_children", 4)
 /* insert delayed */
 #modparam("sipcapture", "db_insert_mode", 1)
+/* activate monitoring/mirroring port capturing. Linux only */
+modparam("sipcapture", "raw_moni_capture_on", 0)
 /* Promiscious mode RAW socket. Mirroring port. Linux only */
 #modparam("sipcapture", "promiscious_on", 1)
-/* activate BPF on mirroring interface */
+/* activate Linux Socket Filter (LSF/BPF) on mirroring interface. Linux only */
 #modparam("sipcapture", "raw_moni_bpf_on", 1)
 
-
 # Main SIP request routing logic
 # - processing of any incoming SIP request starts with this route
 route {

+ 49 - 22
modules/sipcapture/sipcapture.c

@@ -40,6 +40,11 @@
 #include <net/if.h> 
 #include <netdb.h>
 
+/* BPF structure */
+#ifdef __OS_linux
+#include <linux/filter.h>
+#endif
+
 #ifndef __USE_BSD
 #define __USE_BSD  /* on linux use bsd version of iphdr (more portable) */
 #endif /* __USE_BSD */
@@ -205,6 +210,19 @@ str raw_interface = { 0, 0 };
 
 struct ifreq ifr; 	/* interface structure */
 
+#ifdef __OS_linux
+/* Linux socket filter */
+/* tcpdump -s 0 udp and portrange 5060-5090 -dd */
+static struct sock_filter BPF_code[] = { { 0x28, 0, 0, 0x0000000c }, { 0x15, 0, 7, 0x000086dd },
+        { 0x30, 0, 0, 0x00000014 },   { 0x15, 0, 18, 0x00000011 }, { 0x28, 0, 0, 0x00000036 },
+        { 0x35, 0, 1, 0x000013c4 },   { 0x25, 0, 14, 0x000013e2 }, { 0x28, 0, 0, 0x00000038 },
+        { 0x35, 11, 13, 0x000013c4 }, { 0x15, 0, 12, 0x00000800 }, { 0x30, 0, 0, 0x00000017 },
+        { 0x15, 0, 10, 0x00000011 },  { 0x28, 0, 0, 0x00000014 },  { 0x45, 8, 0, 0x00001fff },
+        { 0xb1, 0, 0, 0x0000000e },   { 0x48, 0, 0, 0x0000000e },  { 0x35, 0, 1, 0x000013c4 },
+        { 0x25, 0, 3, 0x000013e2 },   { 0x48, 0, 0, 0x00000010 },  { 0x35, 0, 2, 0x000013c4 },
+        { 0x25, 1, 0, 0x000013e2 },   { 0x6, 0, 0, 0x0000ffff },   { 0x6, 0, 0, 0x00000000 },
+};
+#endif
 
 db1_con_t *db_con = NULL; 		/*!< database connection */
 db_func_t db_funcs;      		/*!< Database functions */
@@ -1301,13 +1319,14 @@ 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)
 {
-	int sock;
+
+	int sock;	
 	
-#if defined (SO_BINDTODEVICE)
+#ifdef __OS_linux
+	struct sock_fprog pf;
 	char short_ifname[sizeof(int)];
 	int ifname_len;
 	char* ifname;
-#endif /* SO_BINDTODEVICE */
  
  	//0x0003 - all packets
 	sock = socket(PF_PACKET, SOCK_RAW, htons(0x0800));
@@ -1317,7 +1336,7 @@ int raw_moni_socket(str* iface, int port_start, int port_end)
 
 	/* set socket options */
 	if (iface && iface->s){
-#if defined (SO_BINDTODEVICE)
+
 		/* workaround for linux bug: arg to setsockopt must have at least
 		 * sizeof(int) size or EINVAL would be returned */
 		if (iface->len<sizeof(int)){
@@ -1329,45 +1348,53 @@ int raw_moni_socket(str* iface, int port_start, int port_end)
 			ifname_len=iface->len;
 			ifname=iface->s;
 		}
-		if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifname, ifname_len)
-						<0){
+		if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifname, ifname_len) <0){
 				ERR("raw_socket: could not bind to %.*s: %s [%d]\n",
 							iface->len, ZSW(iface->s), strerror(errno), errno);
 				goto error;
 		}
-#else /* !SO_BINDTODEVICE */
-		/* SO_BINDTODEVICE is linux specific => cannot bind to a device */
-		ERR("raw_socket: bind to device supported only on linux\n");
-		goto error;
-#endif /* SO_BINDTODEVICE */
 	}
 
 	if(bpf_on) {
-	
+
+		memset(&pf, 0, sizeof(pf));
+	        pf.len = sizeof(BPF_code) / sizeof(BPF_code[0]);
+        	pf.filter = (struct sock_filter *) BPF_code;
+
         	/* Start PORT */
-        	BPF_code[5]  = (struct my_sock_filter)BPF_JUMP(0x35, port_start, 0, 1);
-        	BPF_code[8] = (struct my_sock_filter)BPF_JUMP(0x35, port_start, 11, 13);
-        	BPF_code[16] = (struct my_sock_filter)BPF_JUMP(0x35, port_start, 0, 1);
-        	BPF_code[19] = (struct my_sock_filter)BPF_JUMP(0x35, port_start, 0, 2);
+        	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[16] = (struct sock_filter)BPF_JUMP(0x35, port_start, 0, 1);
+        	BPF_code[19] = (struct sock_filter)BPF_JUMP(0x35, port_start, 0, 2);
         	/* Stop PORT */
-        	BPF_code[6]  = (struct my_sock_filter)BPF_JUMP(0x25, port_end, 0, 14);
-        	BPF_code[17] = (struct my_sock_filter)BPF_JUMP(0x25, port_end, 0, 3);	
-        	BPF_code[20] = (struct my_sock_filter)BPF_JUMP(0x25, port_end, 1, 0);			                                                
+        	BPF_code[6]  = (struct sock_filter)BPF_JUMP(0x25, port_end, 0, 14);
+        	BPF_code[17] = (struct sock_filter)BPF_JUMP(0x25, port_end, 0, 3);	
+        	BPF_code[20] = (struct sock_filter)BPF_JUMP(0x25, port_end, 1, 0);			                                                
 	
         	/* Attach the filter to the socket */
-        	if(setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &Filter, sizeof(Filter)) < 0 ) {
+        	if(setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf)) < 0 ) {
                         ERR(" setsockopt filter: [%s] [%d]\n", strerror(errno), errno);
                 }		
+
+
         }
-	
+
+#else
+        ERR("raw_moni_socket: currently suppoted only on linux\n");
+        goto error;
+#endif
+
 	return sock;
+	
 error:
 	if (sock!=-1) close(sock);
-	return -1;
+	return -1;		
+               		
 }
 
 int raw_moni_rcv_loop(int rsock, int port1, int port2) {
 
+
 	static char buf [BUF_SIZE+1];
 	union sockaddr_union from;
 	union sockaddr_union to;

+ 0 - 53
modules/sipcapture/sipcapture.h

@@ -44,56 +44,3 @@ struct hep_ip6hdr {
         struct in6_addr hp6_dst;        /* destination address */
 };
 #endif
-
-/* Make it independed */
-/* Copied from linux/filter.h */
-struct my_sock_filter      /* Filter block */
-{
-        __u16   code;   /* Actual filter code */
-        __u8    jt;     /* Jump true */
-        __u8    jf;     /* Jump false */
-        __u32   k;      /* Generic multiuse field */
-};
-
-struct my_sock_fprog       /* Required for SO_ATTACH_FILTER. */
-{
-        unsigned short          len;    /* Number of filter blocks */
-        struct my_sock_filter __user *filter;
-};
-
-#ifndef BPF_JUMP
-#define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
-#endif
-
-/* tcpdump -s 0 udp and portrange 5060-5090 -dd */
-static struct my_sock_filter BPF_code[] = {
-		{ 0x28, 0, 0, 0x0000000c },
-		{ 0x15, 0, 7, 0x000086dd },
-		{ 0x30, 0, 0, 0x00000014 },
-		{ 0x15, 0, 18, 0x00000011 },
-		{ 0x28, 0, 0, 0x00000036 },
-		{ 0x35, 0, 1, 0x000013c4 },
-		{ 0x25, 0, 14, 0x000013e2 },
-		{ 0x28, 0, 0, 0x00000038 },
-		{ 0x35, 11, 13, 0x000013c4 },
-		{ 0x15, 0, 12, 0x00000800 },
-		{ 0x30, 0, 0, 0x00000017 },
-		{ 0x15, 0, 10, 0x00000011 },
-		{ 0x28, 0, 0, 0x00000014 },
-		{ 0x45, 8, 0, 0x00001fff },
-		{ 0xb1, 0, 0, 0x0000000e },
-		{ 0x48, 0, 0, 0x0000000e },
-		{ 0x35, 0, 1, 0x000013c4 },
-		{ 0x25, 0, 3, 0x000013e2 },
-		{ 0x48, 0, 0, 0x00000010 },
-		{ 0x35, 0, 2, 0x000013c4 },
-		{ 0x25, 1, 0, 0x000013e2 },
-		{ 0x6, 0, 0, 0x0000ffff },
-		{ 0x6, 0, 0, 0x00000000 },
-};
-
-
-static struct my_sock_fprog Filter = {
-           .len = sizeof(BPF_code) / sizeof(BPF_code[0]),
-           .filter = (struct my_sock_filter *) BPF_code,
-};