Hi Fatih,

you could spoof the natping's source-ip so it would apear to come from the 
same host. I created a patch for that. It uses raw-sockets and works for me 
on linux. 

The patch is made against trunk. To use it, just set the udpping_from 
parameter of module nathelper.

modparam("nathelper", "udpping_from" , "myhost:myport")

Feedback on this would be welcome. 

Best regards, 
Marcus


Fatih Cerit wrote:
> Hi all 
>  
> I am testing nat pinging. I have a natted UA and 2 opensers with 
> diffrent ips. I decided to ping same nat from 2 opensers. I am going to 
> have ability to increase ping interval from 15 seconds to 30 
> seconds. But I don't have any idea that cross pinging works or not. Is 
> there any one at there whom tested before or any suggestions??
> 
> Thanks
> Fatih Cerit 

-- 
Marcus Hunger - [EMAIL PROTECTED]
Telefon: +49 (0)211-63 55 55-61
Telefax: +49 (0)211-63 55 55-22

indigo networks GmbH - Gladbacher Str. 74 - 40219 Düsseldorf
HRB Düsseldorf 39841 - Geschäftsführer: Thilo Salmon, Tim Mois
Steuernummer: 133/5838/1589, Umsatzsteuer-ID: DE219349391

www.sipgate.de - www.sipgate.at - www.sipgate.co.uk
Index: modules/nathelper/nathelper.c
===================================================================
--- modules/nathelper/nathelper.c	(revision 1712)
+++ modules/nathelper/nathelper.c	(working copy)
@@ -154,6 +154,14 @@
 #include <sys/socket.h>
 #include <sys/time.h>
 #include <netinet/in.h>
+#ifndef __USE_BSD
+#define  __USE_BSD
+#endif
+#include <netinet/ip.h>
+#ifndef __FAVOR_BSD
+#define __FAVOR_BSD
+#endif
+#include <netinet/udp.h>
 #include <arpa/inet.h>
 #include <sys/uio.h>
 #include <sys/un.h>
@@ -250,6 +258,7 @@
 static int cblen = 0;
 static int natping_interval = 0;
 struct socket_info* force_socket = 0;
+static int send_raw(const char *buf, int buf_len, union sockaddr_union *to);
 
 
 static struct {
@@ -286,6 +295,7 @@
 static pid_t mypid;
 static unsigned int myseqn = 0;
 static int rcv_avp_no = 42;
+static char *source_host = 0;
 static str nortpproxy_str = str_init("a=nortpproxy:yes\r\n");
 static int sipping_flag = -1;
 
@@ -350,6 +360,7 @@
 	{"sipping_from",          STR_PARAM, &sipping_from.s        },
 	{"sipping_method",        STR_PARAM, &sipping_method.s      },
 	{"sipping_bflag",         INT_PARAM, &sipping_flag          },
+	{"udpping_from",          STR_PARAM, &source_host           },
 	{0, 0, 0}
 };
 
@@ -392,7 +403,67 @@
 	return 0;
 }
 
+static unsigned int source_ip = 0;
+static unsigned int source_port = 0;
+static int raw_sock;
 
+static unsigned int host2addr(char *hostname)
+{
+       struct hostent *he;
+       int ip = 0;
+       char *dp = NULL;
+
+       dp = strchr(hostname, ':');
+       if (dp)
+               *dp = '\0';
+
+       he = resolvehost(hostname, 0);
+
+       if (!he || he->h_addrtype != AF_INET) {
+               LOG(L_ERR, "ERROR:host2addr: only ipv4 addresses allowed\n");
+       } else {
+               memcpy(&ip, he->h_addr_list[0], sizeof(ip));
+       }
+       if (dp)
+               *dp = ':';
+
+       return ip;
+}
+
+static unsigned short host2port(char *hostname)
+{
+       char *dp;
+       unsigned short ret = 5060; // default
+
+       dp = strchr(hostname, ':');
+
+       if (dp) {
+               dp++;
+               ret = atoi(dp);
+       }
+       return ret;
+}
+
+static int init_raw_socket()
+{
+       int on = 1;
+
+       raw_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+
+       if (raw_sock ==-1) {
+               LOG(L_ERR, "ERROR:init_raw_socket: cannot create raw socket\n");
+               return -1;
+       }
+
+       if(setsockopt(raw_sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1) {
+               LOG(L_ERR, "ERROR:init_raw_socket: cannot set socket options\n");
+               return -1;
+       }
+       return raw_sock;
+}
+
+
+
 static int
 mod_init(void)
 {
@@ -407,6 +478,17 @@
 		force_socket=grep_sock_info(&socket_str,0,0);
 	}
 
+	if (source_host && source_host[0]) {
+		source_ip = host2addr(source_host);
+	}
+
+	if (source_ip) {
+		source_port = host2port(source_host);
+		if (init_raw_socket() < 0) {
+			source_ip = 0;
+		}
+	} 
+
 	if (nortpproxy_str.s==NULL || nortpproxy_str.s[0]==0) {
 		nortpproxy_str.len = 0;
 		nortpproxy_str.s = NULL;
@@ -2177,6 +2259,10 @@
 			if (udp_send(send_sock, opt.s, opt.len, &to)<0){
 				LOG(L_ERR, "ERROR:nathelper:nh_timer: sip udp_send failed\n");
 			}
+		} else if (source_ip) {
+			if (send_raw((char *) sbuf, sizeof(sbuf), &to) < 0) {
+				LOG(L_ERR, "ERROR:nathelper:nh_timer: send_raw failed\n");
+			}
 		} else {
 			if (udp_send(send_sock, (char *)sbuf, sizeof(sbuf), &to)<0 ) {
 				LOG(L_ERR, "ERROR:nathelper:nh_timer: udp udp_send failed\n");
@@ -2186,7 +2272,64 @@
 	pkg_free(buf);
 }
 
+u_short checksum(unsigned char *buffer, int len)
+{
+	u_long sum = 0;
 
+	while (len > 1) {
+		sum += *buffer << 8;
+		buffer++;
+		sum += *buffer;
+		buffer++;
+		len -= 2;
+	}
+	if (len) {
+		sum += *buffer << 8;
+	}
+	sum = (sum >> 16) + (sum & 0xffff);
+	sum = (sum >> 16) + (sum);
+
+	return (u_short) ~sum;
+}
+
+static int send_raw(const char *buf, int buf_len, union sockaddr_union *to)
+{
+	struct ip *ip;
+	struct udphdr *udp;
+	unsigned char packet[50];
+	int len = sizeof(struct ip) + sizeof(struct udphdr) + buf_len;
+
+	if (len > sizeof(packet)) {
+		LOG(L_ERR, "ERROR:send_raw: payload too big\n");
+		return -1;
+	}
+
+	ip = (struct ip*) packet;
+	udp = (struct udphdr *) (packet + sizeof(struct ip));
+	memcpy(packet + sizeof(struct ip) + sizeof(struct udphdr), buf, buf_len);
+
+	ip->ip_v = 4;
+	ip->ip_hl = sizeof(struct ip) / 4; // no options
+	ip->ip_tos = 0;
+	ip->ip_len = htons(len);
+	ip->ip_id = 23;
+	ip->ip_off = 0;
+	ip->ip_ttl = 69;
+	ip->ip_p = 17;
+	ip->ip_src.s_addr = source_ip;
+	ip->ip_dst.s_addr = to->sin.sin_addr.s_addr;
+
+	ip->ip_sum = checksum((unsigned char *) ip, sizeof(struct ip));
+
+	udp->uh_sport = htons(source_port);
+	udp->uh_dport = to->sin.sin_port;
+	udp->uh_ulen = htons((unsigned short) sizeof(struct udphdr) + buf_len);
+	udp->uh_sum = 0;
+
+	return sendto(raw_sock, packet, len, 0, (struct sockaddr *) to, sizeof(struct sockaddr_in));
+}
+
+
 /*
  * Create received SIP uri that will be either
  * passed to registrar in an AVP or apended
_______________________________________________
Users mailing list
[email protected]
http://openser.org/cgi-bin/mailman/listinfo/users

Reply via email to