Module: sip-router Branch: master Commit: dc4cdb294cc135a01032dd613d79bfe625351612 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=dc4cdb29...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@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);