modules/lcr: Fixed to/from_gw tests when proto parameter is 0 (ANY)
[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 /** inernal ip addresses representation functions.
38  * @file ip_addr.c
39  * @ingroup core
40  * Module: @ref core
41  */
42
43
44 #include <stdlib.h>
45 #include <stdio.h>
46
47 #include "ip_addr.h"
48 #include "dprint.h"
49 #include "mem/mem.h"
50 #include "resolve.h"
51 #include "trim.h"
52
53
54 struct net* mk_new_net(struct ip_addr* ip, struct ip_addr* mask)
55 {
56         struct net* n;
57         int warning;
58         int r;
59         
60         warning=0;
61         if ((ip->af != mask->af) || (ip->len != mask->len)){
62                 LOG(L_CRIT, "ERROR: mk_net: trying to use a different mask family"
63                                 " (eg. ipv4/ipv6mask or ipv6/ipv4mask)\n");
64                 goto error;
65         }
66         n=(struct net*)pkg_malloc(sizeof(struct net));
67         if (n==0){ 
68                 LOG(L_CRIT, "ERROR: mk_net: memory allocation failure\n");
69                 goto error;
70         }
71         n->ip=*ip;
72         n->mask=*mask;
73         for (r=0; r<n->ip.len/4; r++) { /*ipv4 & ipv6 addresses are multiple of 4*/
74                 n->ip.u.addr32[r] &= n->mask.u.addr32[r];
75                 if (n->ip.u.addr32[r]!=ip->u.addr32[r]) warning=1;
76         };
77         if (warning){
78                 LOG(L_WARN, "WARNING: mk_net: invalid network address/netmask "
79                                         "combination fixed...\n");
80                 print_ip("original network address:", ip, "/");
81                 print_ip("", mask, "\n");
82                 print_ip("fixed    network address:", &(n->ip), "/");
83                 print_ip("", &(n->mask), "\n");
84         };
85         return n;
86 error:
87         return 0;
88 }
89
90
91
92 struct net* mk_new_net_bitlen(struct ip_addr* ip, unsigned int bitlen)
93 {
94         struct ip_addr mask;
95         int r;
96         
97         if (bitlen>ip->len*8){
98                 LOG(L_CRIT, "ERROR: mk_net_bitlen: bad bitlen number %d\n", bitlen);
99                 goto error;
100         }
101         memset(&mask,0, sizeof(mask));
102         for (r=0;r<bitlen/8;r++) mask.u.addr[r]=0xff;
103         if (bitlen%8) mask.u.addr[r]=  ~((1<<(8-(bitlen%8)))-1);
104         mask.af=ip->af;
105         mask.len=ip->len;
106         
107         return mk_new_net(ip, &mask);
108 error:
109         return 0;
110 }
111
112
113
114 /** fills a net structure from an ip and a mask.
115  *
116  * This function will not print any error messages or allocate
117  * memory (as opposed to mk_new_net() above).
118  *
119  * @param n - destination net structure
120  * @param ip
121  * @param mask
122  * @return -1 on error (af mismatch), 0 on success
123  */
124 int mk_net(struct net* n, struct ip_addr* ip, struct ip_addr* mask)
125 {
126         int r;
127         
128         if (unlikely((ip->af != mask->af) || (ip->len != mask->len))) {
129                 return -1;
130         }
131         n->ip=*ip;
132         n->mask=*mask;
133         /* fix the network part of the mask */
134         for (r=0; r<n->ip.len/4; r++) { /*ipv4 & ipv6 addresses are multiple of 4*/
135                 n->ip.u.addr32[r] &= n->mask.u.addr32[r];
136         };
137         return 0;
138 }
139
140
141
142 /** fills a net structure from an ip and a bitlen.
143  *
144  * This function will not print any error messages or allocate
145  * memory (as opposed to mk_new_net_bitlen() above).
146  *
147  * @param n - destination net structure
148  * @param ip
149  * @param bitlen
150  * @return -1 on error (af mismatch), 0 on success
151  */
152 int mk_net_bitlen(struct net* n, struct ip_addr* ip, unsigned int bitlen)
153 {
154         struct ip_addr mask;
155         int r;
156         
157         if (unlikely(bitlen>ip->len*8))
158                 /* bitlen too big */
159                 return -1;
160         memset(&mask,0, sizeof(mask));
161         for (r=0;r<bitlen/8;r++) mask.u.addr[r]=0xff;
162         if (bitlen%8) mask.u.addr[r]=  ~((1<<(8-(bitlen%8)))-1);
163         mask.af=ip->af;
164         mask.len=ip->len;
165         
166         return mk_net(n, ip, &mask);
167 }
168
169
170
171 /** initializes a net structure from a string.
172  * @param dst - net structure that will be filled
173  * @param s - string of the form "ip", "ip/mask_len" or "ip/ip_mak".
174  * @return -1 on error, 0 on succes
175  */
176 int mk_net_str(struct net* dst, str* s)
177 {
178         struct ip_addr* t;
179         char* p;
180         struct ip_addr ip;
181         str addr;
182         str mask;
183         unsigned int bitlen;
184         
185         /* test for ip only */
186         t = str2ip(s);
187 #ifdef USE_IPV6
188         if (unlikely(t == 0))
189                 t = str2ip6(s);
190 #endif /* USE_IPV6 */
191         if (likely(t))
192                 return mk_net_bitlen(dst, t, t->len*8);
193         /* not a simple ip, maybe an ip/netmask pair */
194         p = q_memchr(s->s, '/', s->len);
195         if (likely(p)) {
196                 addr.s = s->s;
197                 addr.len = (int)(long)(p - s->s);
198                 mask.s = p + 1;
199                 mask.len = s->len - (addr.len + 1);
200                 /* allow '/' enclosed by whitespace */
201                 trim_trailing(&addr);
202                 trim_leading(&mask);
203                 t = str2ip(&addr);
204                 if (likely(t)) {
205                         /* it can be a number */
206                         if (str2int(&mask, &bitlen) == 0)
207                                 return mk_net_bitlen(dst, t, bitlen);
208                         ip = *t;
209                         t = str2ip(&mask);
210                         if (likely(t))
211                                 return mk_net(dst, &ip, t);
212                         /* error */
213                         return -1;
214                 }
215 #ifdef USE_IPV6
216                 else {
217                         t = str2ip6(&addr);
218                         if (likely(t)) {
219                                 /* it can be a number */
220                                 if (str2int(&mask, &bitlen) == 0)
221                                         return mk_net_bitlen(dst, t, bitlen);
222                                 ip = *t;
223                                 t = str2ip6(&mask);
224                                 if (likely(t))
225                                         return mk_net(dst, &ip, t);
226                                 /* error */
227                                 return -1;
228                         }
229                 }
230 #endif /* USE_IPV6 */
231         }
232         return -1;
233 }
234
235
236
237 void print_ip(char* p, struct ip_addr* ip, char *s)
238 {
239         switch(ip->af){
240                 case AF_INET:
241                         DBG("%s%d.%d.%d.%d%s", (p)?p:"",
242                                                                 ip->u.addr[0],
243                                                                 ip->u.addr[1],
244                                                                 ip->u.addr[2],
245                                                                 ip->u.addr[3],
246                                                                 (s)?s:""
247                                                                 );
248                         break;
249 #ifdef USE_IPV6
250                 case AF_INET6:
251                         DBG("%s%x:%x:%x:%x:%x:%x:%x:%x%s", (p)?p:"",
252                                                                                         htons(ip->u.addr16[0]),
253                                                                                         htons(ip->u.addr16[1]),
254                                                                                         htons(ip->u.addr16[2]),
255                                                                                         htons(ip->u.addr16[3]),
256                                                                                         htons(ip->u.addr16[4]),
257                                                                                         htons(ip->u.addr16[5]),
258                                                                                         htons(ip->u.addr16[6]),
259                                                                                         htons(ip->u.addr16[7]),
260                                                                                         (s)?s:""
261                                 );
262                         break;
263 #endif /* USE_IPV6 */
264                 default:
265                         DBG("print_ip: warning unknown address family %d\n", ip->af);
266         }
267 }
268
269
270
271 void stdout_print_ip(struct ip_addr* ip)
272 {
273         switch(ip->af){
274                 case AF_INET:
275                         printf("%d.%d.%d.%d",   ip->u.addr[0],
276                                                                 ip->u.addr[1],
277                                                                 ip->u.addr[2],
278                                                                 ip->u.addr[3]);
279                         break;
280 #ifdef USE_IPV6
281                 case AF_INET6:
282                         printf("%x:%x:%x:%x:%x:%x:%x:%x",       htons(ip->u.addr16[0]),
283                                                                                         htons(ip->u.addr16[1]),
284                                                                                         htons(ip->u.addr16[2]),
285                                                                                         htons(ip->u.addr16[3]),
286                                                                                         htons(ip->u.addr16[4]),
287                                                                                         htons(ip->u.addr16[5]),
288                                                                                         htons(ip->u.addr16[6]),
289                                                                                         htons(ip->u.addr16[7])
290                                 );
291                         break;
292 #endif /* USE_IPV6 */
293                 default:
294                         DBG("print_ip: warning unknown address family %d\n", ip->af);
295         }
296 }
297
298
299
300 void print_net(struct net* net)
301 {
302         if (net==0){
303                 LOG(L_WARN, "ERROR: print net: null pointer\n");
304                 return;
305         }
306         print_ip("", &net->ip, "/"); print_ip("", &net->mask, "");
307 }
308
309
310 #ifdef USE_MCAST
311
312 /* Returns 1 if the given address is a multicast address */
313 int is_mcast(struct ip_addr* ip)
314 {
315         if (!ip){
316                 LOG(L_ERR, "ERROR: is_mcast: Invalid parameter value\n");
317                 return -1;
318         }
319
320         if (ip->af==AF_INET){
321                 return IN_MULTICAST(htonl(ip->u.addr32[0]));
322 #ifdef USE_IPV6
323         } else if (ip->af==AF_INET6){
324                 return IN6_IS_ADDR_MULTICAST((struct in6_addr*)ip->u.addr32);
325 #endif /* USE_IPV6 */
326         } else {
327                 LOG(L_ERR, "ERROR: is_mcast: Unsupported protocol family\n");
328                 return -1;
329         }
330 }
331
332 #endif /* USE_MCAST */
333
334
335
336 /** get protocol name (asciiz).
337  * @param proto - protocol number
338  * @return  string with the protocol name or "unknown".
339  */
340 char* get_proto_name(unsigned int proto)
341 {
342         switch(proto){
343                 case PROTO_NONE:
344                         return "*";
345                 case PROTO_UDP:
346                         return "udp";
347                 case PROTO_TCP:
348                         return "tcp";
349                 case PROTO_TLS:
350                         return "tls";
351                 case PROTO_SCTP:
352                         return "sctp";
353                 default:
354                         return "unknown";
355         }
356 }
357
358
359 /**
360  * match ip address with net address and bitmask
361  * - return 0 on match, -1 otherwise
362  */
363 int ip_addr_match_net(ip_addr_t *iaddr, ip_addr_t *naddr,
364                 int mask)
365 {
366         unsigned char c;
367         int i;
368         int mbytes;
369         int mbits;
370
371         if(mask==0)
372                 return 0;
373         if(iaddr==NULL || naddr==NULL || mask<0)
374                 return -1;
375         if(iaddr->af != naddr->af)
376                 return -1;
377
378         if(iaddr->af == AF_INET)
379         {
380                 if(mask>32)
381                         return -1;
382                 if(mask==32)
383                 {
384                         if(ip_addr_cmp(iaddr, naddr))
385                                 return 0;
386                         return -1;
387                 }
388         } else if(iaddr->af ==  AF_INET6) {
389                 if(mask>128)
390                         return -1;
391
392                 if(mask==128)
393                 {
394                         if(ip_addr_cmp(iaddr, naddr))
395                                 return 0;
396                         return -1;
397                 }
398         }
399
400         mbytes = mask / 8;
401         for(i=0; i<mbytes; i++)
402         {
403                 if(iaddr->u.addr[i] != naddr->u.addr[i])
404                         return -1;
405         }
406         mbits = mask % 8;
407         if(mbits==0)
408                 return 0;
409         c = naddr->u.addr[i] & (~((1 << (8 - mbits)) - 1));
410         if((iaddr->u.addr[i] & c) == c)
411                 return 0;
412         return -1;
413 }