Merge commit 'origin/daniel/pv'
[sip-router] / ip_addr.c
1 /*
2  * $Id$
3  *
4  *
5  * ip address & address family related functions
6  *
7  * Copyright (C) 2001-2003 FhG Fokus
8  *
9  * This file is part of ser, a free SIP server.
10  *
11  * ser is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version
15  *
16  * For a license to use the ser software under conditions
17  * other than those described here, or to purchase support for this
18  * software, please contact iptel.org by e-mail at the following addresses:
19  *    info@iptel.org
20  *
21  * ser is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License 
27  * along with this program; if not, write to the Free Software 
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29  */
30 /*
31  * History:
32  * --------
33  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free
34  *  2004-10-01  mk_net fixes bad network addresses now (andrei)
35  */
36
37
38 #include <stdlib.h>
39 #include <stdio.h>
40
41 #include "ip_addr.h"
42 #include "dprint.h"
43 #include "mem/mem.h"
44
45
46 struct net* mk_net(struct ip_addr* ip, struct ip_addr* mask)
47 {
48         struct net* n;
49         int warning;
50         int r;
51         
52         warning=0;
53         if ((ip->af != mask->af) || (ip->len != mask->len)){
54                 LOG(L_CRIT, "ERROR: mk_net: trying to use a different mask family"
55                                 " (eg. ipv4/ipv6mask or ipv6/ipv4mask)\n");
56                 goto error;
57         }
58         n=(struct net*)pkg_malloc(sizeof(struct net));
59         if (n==0){ 
60                 LOG(L_CRIT, "ERROR: mk_net: memory allocation failure\n");
61                 goto error;
62         }
63         n->ip=*ip;
64         n->mask=*mask;
65         for (r=0; r<n->ip.len/4; r++) { /*ipv4 & ipv6 addresses are multiple of 4*/
66                 n->ip.u.addr32[r] &= n->mask.u.addr32[r];
67                 if (n->ip.u.addr32[r]!=ip->u.addr32[r]) warning=1;
68         };
69         if (warning){
70                 LOG(L_WARN, "WARNING: mk_net: invalid network address/netmask "
71                                         "combination fixed...\n");
72                 print_ip("original network address:", ip, "/");
73                 print_ip("", mask, "\n");
74                 print_ip("fixed    network address:", &(n->ip), "/");
75                 print_ip("", &(n->mask), "\n");
76         };
77         return n;
78 error:
79         return 0;
80 }
81
82
83
84 struct net* mk_net_bitlen(struct ip_addr* ip, unsigned int bitlen)
85 {
86         struct ip_addr mask;
87         int r;
88         
89         if (bitlen>ip->len*8){
90                 LOG(L_CRIT, "ERROR: mk_net_bitlen: bad bitlen number %d\n", bitlen);
91                 goto error;
92         }
93         memset(&mask,0, sizeof(mask));
94         for (r=0;r<bitlen/8;r++) mask.u.addr[r]=0xff;
95         if (bitlen%8) mask.u.addr[r]=  ~((1<<(8-(bitlen%8)))-1);
96         mask.af=ip->af;
97         mask.len=ip->len;
98         
99         return mk_net(ip, &mask);
100 error:
101         return 0;
102 }
103
104
105
106 void print_ip(char* p, struct ip_addr* ip, char *s)
107 {
108         switch(ip->af){
109                 case AF_INET:
110                         DBG("%s%d.%d.%d.%d%s", (p)?p:"",
111                                                                 ip->u.addr[0],
112                                                                 ip->u.addr[1],
113                                                                 ip->u.addr[2],
114                                                                 ip->u.addr[3],
115                                                                 (s)?s:""
116                                                                 );
117                         break;
118 #ifdef USE_IPV6
119                 case AF_INET6:
120                         DBG("%s%x:%x:%x:%x:%x:%x:%x:%x%s", (p)?p:"",
121                                                                                         htons(ip->u.addr16[0]),
122                                                                                         htons(ip->u.addr16[1]),
123                                                                                         htons(ip->u.addr16[2]),
124                                                                                         htons(ip->u.addr16[3]),
125                                                                                         htons(ip->u.addr16[4]),
126                                                                                         htons(ip->u.addr16[5]),
127                                                                                         htons(ip->u.addr16[6]),
128                                                                                         htons(ip->u.addr16[7]),
129                                                                                         (s)?s:""
130                                 );
131                         break;
132 #endif /* USE_IPV6 */
133                 default:
134                         DBG("print_ip: warning unknown address family %d\n", ip->af);
135         }
136 }
137
138
139
140 void stdout_print_ip(struct ip_addr* ip)
141 {
142         switch(ip->af){
143                 case AF_INET:
144                         printf("%d.%d.%d.%d",   ip->u.addr[0],
145                                                                 ip->u.addr[1],
146                                                                 ip->u.addr[2],
147                                                                 ip->u.addr[3]);
148                         break;
149 #ifdef USE_IPV6
150                 case AF_INET6:
151                         printf("%x:%x:%x:%x:%x:%x:%x:%x",       htons(ip->u.addr16[0]),
152                                                                                         htons(ip->u.addr16[1]),
153                                                                                         htons(ip->u.addr16[2]),
154                                                                                         htons(ip->u.addr16[3]),
155                                                                                         htons(ip->u.addr16[4]),
156                                                                                         htons(ip->u.addr16[5]),
157                                                                                         htons(ip->u.addr16[6]),
158                                                                                         htons(ip->u.addr16[7])
159                                 );
160                         break;
161 #endif /* USE_IPV6 */
162                 default:
163                         DBG("print_ip: warning unknown address family %d\n", ip->af);
164         }
165 }
166
167
168
169 void print_net(struct net* net)
170 {
171         if (net==0){
172                 LOG(L_WARN, "ERROR: print net: null pointer\n");
173                 return;
174         }
175         print_ip("", &net->ip, "/"); print_ip("", &net->mask, "");
176 }
177
178
179 #ifdef USE_MCAST
180
181 /* Returns 1 if the given address is a multicast address */
182 int is_mcast(struct ip_addr* ip)
183 {
184         if (!ip){
185                 LOG(L_ERR, "ERROR: is_mcast: Invalid parameter value\n");
186                 return -1;
187         }
188
189         if (ip->af==AF_INET){
190                 return IN_MULTICAST(htonl(ip->u.addr32[0]));
191 #ifdef USE_IPV6
192         } else if (ip->af==AF_INET6){
193                 return IN6_IS_ADDR_MULTICAST((struct in6_addr*)ip->u.addr32);
194 #endif /* USE_IPV6 */
195         } else {
196                 LOG(L_ERR, "ERROR: is_mcast: Unsupported protocol family\n");
197                 return -1;
198         }
199 }
200
201 #endif /* USE_MCAST */