parser/sdp: more suggestive debug message
[sip-router] / ip_addr.c
index 3efdeb9..c071f83 100644 (file)
--- a/ip_addr.c
+++ b/ip_addr.c
  *  2004-10-01  mk_net fixes bad network addresses now (andrei)
  */
 
+/** inernal ip addresses representation functions.
+ * @file ip_addr.c
+ * @ingroup core
+ * Module: @ref core
+ */
+
 
 #include <stdlib.h>
 #include <stdio.h>
 #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;
@@ -81,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;
@@ -96,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){
@@ -199,3 +330,88 @@ int is_mcast(struct ip_addr* ip)
 }
 
 #endif /* USE_MCAST */
+
+
+
+/** get protocol name (asciiz).
+ * @param proto - protocol number
+ * @return  string with the protocol name or "unknown".
+ */
+char* get_proto_name(unsigned int proto)
+{
+       switch(proto){
+               case PROTO_NONE:
+                       return "*";
+               case PROTO_UDP:
+                       return "udp";
+               case PROTO_TCP:
+                       return "tcp";
+               case PROTO_TLS:
+                       return "tls";
+               case PROTO_SCTP:
+                       return "sctp";
+               case PROTO_WS:
+                       return "ws";
+               case PROTO_WSS:
+                       return "wss";
+               default:
+                       return "unknown";
+       }
+}
+
+
+/**
+ * match ip address with net address and bitmask
+ * - return 0 on match, -1 otherwise
+ */
+int ip_addr_match_net(ip_addr_t *iaddr, ip_addr_t *naddr,
+               int mask)
+{
+       unsigned char c;
+       int i;
+       int mbytes;
+       int mbits;
+
+       if(mask==0)
+               return 0;
+       if(iaddr==NULL || naddr==NULL || mask<0)
+               return -1;
+       if(iaddr->af != naddr->af)
+               return -1;
+
+       if(iaddr->af == AF_INET)
+       {
+               if(mask>32)
+                       return -1;
+               if(mask==32)
+               {
+                       if(ip_addr_cmp(iaddr, naddr))
+                               return 0;
+                       return -1;
+               }
+       } else if(iaddr->af ==  AF_INET6) {
+               if(mask>128)
+                       return -1;
+
+               if(mask==128)
+               {
+                       if(ip_addr_cmp(iaddr, naddr))
+                               return 0;
+                       return -1;
+               }
+       }
+
+       mbytes = mask / 8;
+       for(i=0; i<mbytes; i++)
+       {
+               if(iaddr->u.addr[i] != naddr->u.addr[i])
+                       return -1;
+       }
+       mbits = mask % 8;
+       if(mbits==0)
+               return 0;
+       c = naddr->u.addr[i] & (~((1 << (8 - mbits)) - 1));
+       if((iaddr->u.addr[i] & c) == c)
+               return 0;
+       return -1;
+}