[sr-dev] git:master: core: functions for parsing a network address

Andrei Pelinescu-Onciul andrei at iptel.org
Fri Jun 18 22:34:55 CEST 2010


Module: sip-router
Branch: master
Commit: dc4cdb294cc135a01032dd613d79bfe625351612
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=dc4cdb294cc135a01032dd613d79bfe625351612

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at iptel.org>
Date:   Fri Jun 18 22:03:46 2010 +0200

core: functions for parsing a network address

- added mk_net_str(): initialize a struct net from a string of the
  form ip/mask, ip/bitlen or ip
- renamed mk_net() and mk_net_bitlen() to  mk_new_net() and
  mk_new_net_bitlen()

---

 cfg.y     |   10 ++--
 ip_addr.c |  140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 ip_addr.h |    7 ++-
 3 files changed, 142 insertions(+), 15 deletions(-)

diff --git a/cfg.y b/cfg.y
index ae214f2..f2b71a5 100644
--- a/cfg.y
+++ b/cfg.y
@@ -2073,7 +2073,7 @@ exp_elem:
 				pkg_free(s_tmp.s);
 				if (ip_tmp) {
 					$$=mk_elem($2, $1, 0, NET_ST, 
-								mk_net_bitlen(ip_tmp, ip_tmp->len*8) );
+								mk_new_net_bitlen(ip_tmp, ip_tmp->len*8) );
 				} else {
 					$$=mk_elem($2, $1, 0, RVE_ST, $3);
 				}
@@ -2113,19 +2113,19 @@ exp_elem2:
 */
 
 ipnet:
-	ip SLASH ip	{ $$=mk_net($1, $3); }
+	ip SLASH ip	{ $$=mk_new_net($1, $3); }
 	| ip SLASH NUMBER {
 		if (($3<0) || ($3>$1->len*8)) {
 			yyerror("invalid bit number in netmask");
 			$$=0;
 		} else {
-			$$=mk_net_bitlen($1, $3);
+			$$=mk_new_net_bitlen($1, $3);
 		/*
-			$$=mk_net($1, htonl( ($3)?~( (1<<(32-$3))-1 ):0 ) );
+			$$=mk_new_net($1, htonl( ($3)?~( (1<<(32-$3))-1 ):0 ) );
 		*/
 		}
 	}
-	| ip	{ $$=mk_net_bitlen($1, $1->len*8); }
+	| ip	{ $$=mk_new_net_bitlen($1, $1->len*8); }
 	| ip SLASH error { $$=0; yyerror("netmask (eg:255.0.0.0 or 8) expected"); }
 	;
 
diff --git a/ip_addr.c b/ip_addr.c
index 06a5bf2..5651809 100644
--- a/ip_addr.c
+++ b/ip_addr.c
@@ -34,11 +34,10 @@
  *  2004-10-01  mk_net fixes bad network addresses now (andrei)
  */
 
-/*!
- * \file
- * \brief SIP-router core :: 
- * \ingroup core
- * Module: \ref core
+/** inernal ip addresses representation functions.
+ * @file ip_addr.c
+ * @ingroup core
+ * Module: @ref core
  */
 
 
@@ -48,9 +47,11 @@
 #include "ip_addr.h"
 #include "dprint.h"
 #include "mem/mem.h"
+#include "resolve.h"
+#include "trim.h"
 
 
-struct net* mk_net(struct ip_addr* ip, struct ip_addr* mask)
+struct net* mk_new_net(struct ip_addr* ip, struct ip_addr* mask)
 {
 	struct net* n;
 	int warning;
@@ -88,7 +89,7 @@ error:
 
 
 
-struct net* mk_net_bitlen(struct ip_addr* ip, unsigned int bitlen)
+struct net* mk_new_net_bitlen(struct ip_addr* ip, unsigned int bitlen)
 {
 	struct ip_addr mask;
 	int r;
@@ -103,13 +104,136 @@ struct net* mk_net_bitlen(struct ip_addr* ip, unsigned int bitlen)
 	mask.af=ip->af;
 	mask.len=ip->len;
 	
-	return mk_net(ip, &mask);
+	return mk_new_net(ip, &mask);
 error:
 	return 0;
 }
 
 
 
+/** fills a net structure from an ip and a mask.
+ *
+ * This function will not print any error messages or allocate
+ * memory (as opposed to mk_new_net() above).
+ *
+ * @param n - destination net structure
+ * @param ip
+ * @param mask
+ * @return -1 on error (af mismatch), 0 on success
+ */
+int mk_net(struct net* n, struct ip_addr* ip, struct ip_addr* mask)
+{
+	int r;
+	
+	if (unlikely((ip->af != mask->af) || (ip->len != mask->len))) {
+		return -1;
+	}
+	n->ip=*ip;
+	n->mask=*mask;
+	/* fix the network part of the mask */
+	for (r=0; r<n->ip.len/4; r++) { /*ipv4 & ipv6 addresses are multiple of 4*/
+		n->ip.u.addr32[r] &= n->mask.u.addr32[r];
+	};
+	return 0;
+}
+
+
+
+/** fills a net structure from an ip and a bitlen.
+ *
+ * This function will not print any error messages or allocate
+ * memory (as opposed to mk_new_net_bitlen() above).
+ *
+ * @param n - destination net structure
+ * @param ip
+ * @param bitlen
+ * @return -1 on error (af mismatch), 0 on success
+ */
+int mk_net_bitlen(struct net* n, struct ip_addr* ip, unsigned int bitlen)
+{
+	struct ip_addr mask;
+	int r;
+	
+	if (unlikely(bitlen>ip->len*8))
+		/* bitlen too big */
+		return -1;
+	memset(&mask,0, sizeof(mask));
+	for (r=0;r<bitlen/8;r++) mask.u.addr[r]=0xff;
+	if (bitlen%8) mask.u.addr[r]=  ~((1<<(8-(bitlen%8)))-1);
+	mask.af=ip->af;
+	mask.len=ip->len;
+	
+	return mk_net(n, ip, &mask);
+}
+
+
+
+/** initializes a net structure from a string.
+ * @param dst - net structure that will be filled
+ * @param s - string of the form "ip", "ip/mask_len" or "ip/ip_mak".
+ * @return -1 on error, 0 on succes
+ */
+int mk_net_str(struct net* dst, str* s)
+{
+	struct ip_addr* t;
+	char* p;
+	struct ip_addr ip;
+	str addr;
+	str mask;
+	unsigned int bitlen;
+	
+	/* test for ip only */
+	t = str2ip(s);
+#ifdef USE_IPV6
+	if (unlikely(t == 0))
+		t = str2ip6(s);
+#endif /* USE_IPV6 */
+	if (likely(t))
+		return mk_net_bitlen(dst, t, t->len*8);
+	/* not a simple ip, maybe an ip/netmask pair */
+	p = q_memchr(s->s, '/', s->len);
+	if (likely(p)) {
+		addr.s = s->s;
+		addr.len = (int)(long)(p - s->s);
+		mask.s = p + 1;
+		mask.len = s->len - (addr.len + 1);
+		/* allow '/' enclosed by whitespace */
+		trim_trailing(&addr);
+		trim_leading(&mask);
+		t = str2ip(&addr);
+		if (likely(t)) {
+			/* it can be a number */
+			if (str2int(&mask, &bitlen) == 0)
+				return mk_net_bitlen(dst, t, bitlen);
+			ip = *t;
+			t = str2ip(&mask);
+			if (likely(t))
+				return mk_net(dst, &ip, t);
+			/* error */
+			return -1;
+		}
+#ifdef USE_IPV6
+		else {
+			t = str2ip6(&addr);
+			if (likely(t)) {
+				/* it can be a number */
+				if (str2int(&mask, &bitlen) == 0)
+					return mk_net_bitlen(dst, t, bitlen);
+				ip = *t;
+				t = str2ip6(&mask);
+				if (likely(t))
+					return mk_net(dst, &ip, t);
+				/* error */
+				return -1;
+			}
+		}
+#endif /* USE_IPV6 */
+	}
+	return -1;
+}
+
+
+
 void print_ip(char* p, struct ip_addr* ip, char *s)
 {
 	switch(ip->af){
diff --git a/ip_addr.h b/ip_addr.h
index fd19c42..50fbf58 100644
--- a/ip_addr.h
+++ b/ip_addr.h
@@ -240,8 +240,11 @@ struct socket_id{
 
 
 
-struct net* mk_net(struct ip_addr* ip, struct ip_addr* mask);
-struct net* mk_net_bitlen(struct ip_addr* ip, unsigned int bitlen);
+struct net* mk_new_net(struct ip_addr* ip, struct ip_addr* mask);
+struct net* mk_new_net_bitlen(struct ip_addr* ip, unsigned int bitlen);
+int mk_net(struct net* n, struct ip_addr* ip, struct ip_addr* mask);
+int mk_net_bitlen(struct net* n, struct ip_addr* ip, unsigned int bitlen);
+int mk_net_str(struct net* dst, str* s);
 
 void print_ip(char* prefix, struct ip_addr* ip, char* suffix);
 void stdout_print_ip(struct ip_addr* ip);




More information about the sr-dev mailing list