123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- /*
- * $Id$
- *
- *
- * ip address & address family related functions
- *
- * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- * [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- /*
- * History:
- * --------
- * 2003-03-19 replaced all mallocs/frees w/ pkg_malloc/pkg_free
- * 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_new_net(struct ip_addr* ip, struct ip_addr* mask)
- {
- struct net* n;
- int warning;
- int r;
-
- warning=0;
- if ((ip->af != mask->af) || (ip->len != mask->len)){
- LM_CRIT("trying to use a different mask family"
- " (eg. ipv4/ipv6mask or ipv6/ipv4mask)\n");
- goto error;
- }
- n=(struct net*)pkg_malloc(sizeof(struct net));
- if (n==0){
- LM_CRIT("memory allocation failure\n");
- goto error;
- }
- n->ip=*ip;
- n->mask=*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];
- if (n->ip.u.addr32[r]!=ip->u.addr32[r]) warning=1;
- };
- if (warning){
- LM_WARN("invalid network address/netmask "
- "combination fixed...\n");
- print_ip("original network address:", ip, "/");
- print_ip("", mask, "\n");
- print_ip("fixed network address:", &(n->ip), "/");
- print_ip("", &(n->mask), "\n");
- };
- return n;
- error:
- return 0;
- }
- struct net* mk_new_net_bitlen(struct ip_addr* ip, unsigned int bitlen)
- {
- struct ip_addr mask;
- int r;
-
- if (bitlen>ip->len*8){
- LM_CRIT("bad bitlen number %d\n", bitlen);
- goto error;
- }
- 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_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);
- if (unlikely(t == 0))
- t = str2ip6(s);
- 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;
- }
- 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;
- }
- }
- }
- return -1;
- }
- void print_ip(char* p, struct ip_addr* ip, char *s)
- {
- switch(ip->af){
- case AF_INET:
- DBG("%s%d.%d.%d.%d%s", (p)?p:"",
- ip->u.addr[0],
- ip->u.addr[1],
- ip->u.addr[2],
- ip->u.addr[3],
- (s)?s:""
- );
- break;
- case AF_INET6:
- DBG("%s%x:%x:%x:%x:%x:%x:%x:%x%s", (p)?p:"",
- htons(ip->u.addr16[0]),
- htons(ip->u.addr16[1]),
- htons(ip->u.addr16[2]),
- htons(ip->u.addr16[3]),
- htons(ip->u.addr16[4]),
- htons(ip->u.addr16[5]),
- htons(ip->u.addr16[6]),
- htons(ip->u.addr16[7]),
- (s)?s:""
- );
- break;
- default:
- DBG("print_ip: warning unknown address family %d\n", ip->af);
- }
- }
- void stdout_print_ip(struct ip_addr* ip)
- {
- switch(ip->af){
- case AF_INET:
- printf("%d.%d.%d.%d", ip->u.addr[0],
- ip->u.addr[1],
- ip->u.addr[2],
- ip->u.addr[3]);
- break;
- case AF_INET6:
- printf("%x:%x:%x:%x:%x:%x:%x:%x", htons(ip->u.addr16[0]),
- htons(ip->u.addr16[1]),
- htons(ip->u.addr16[2]),
- htons(ip->u.addr16[3]),
- htons(ip->u.addr16[4]),
- htons(ip->u.addr16[5]),
- htons(ip->u.addr16[6]),
- htons(ip->u.addr16[7])
- );
- break;
- default:
- DBG("print_ip: warning unknown address family %d\n", ip->af);
- }
- }
- void print_net(struct net* net)
- {
- if (net==0){
- LM_WARN("null pointer\n");
- return;
- }
- print_ip("", &net->ip, "/"); print_ip("", &net->mask, "");
- }
- #ifdef USE_MCAST
- /* Returns 1 if the given address is a multicast address */
- int is_mcast(struct ip_addr* ip)
- {
- if (!ip){
- LM_ERR("Invalid parameter value\n");
- return -1;
- }
- if (ip->af==AF_INET){
- return IN_MULTICAST(htonl(ip->u.addr32[0]));
- } else if (ip->af==AF_INET6){
- return IN6_IS_ADDR_MULTICAST((struct in6_addr*)ip->u.addr32);
- } else {
- LM_ERR("Unsupported protocol family\n");
- return -1;
- }
- }
- #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:
- case PROTO_WSS:
- return "ws";
- 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;
- }
- int si_get_signaling_data(struct socket_info *si, str **addr, str **port)
- {
- if(si==NULL)
- return -1;
- if(addr) {
- if(si->useinfo.name.len>0) {
- *addr = &si->useinfo.name;
- } else {
- *addr = &si->address_str;
- }
- }
- if(port) {
- if(si->useinfo.port_no>0) {
- *port = &si->useinfo.port_no_str;
- } else {
- *port = &si->port_no_str;
- }
- }
- return 0;
- }
|