9242116afab3a339a6ace798508112f0b537ed44
[sip-router] / ip_addr.h
1 /* $Id$
2  *
3  * ip address family realted structures
4  *
5  * Copyright (C) 2001-2003 Fhg Fokus
6  *
7  * This file is part of ser, a free SIP server.
8  *
9  * ser is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version
13  *
14  * For a license to use the ser software under conditions
15  * other than those described here, or to purchase support for this
16  * software, please contact iptel.org by e-mail at the following addresses:
17  *    info@iptel.org
18  *
19  * ser is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License 
25  * along with this program; if not, write to the Free Software 
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27  */
28
29
30 #ifndef ip_addr_h
31 #define ip_addr_h
32
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <netdb.h>
38 #include "str.h"
39
40
41 #include "dprint.h"
42
43 #define SOCKET_TCP      1
44 #define SOCKET_UDP      0
45
46 struct ip_addr{
47         unsigned int af; /* address family: AF_INET6 or AF_INET */
48         unsigned int len;    /* address len, 16 or 4 */
49         
50         /* 64 bits alligned address */
51         union {
52                 unsigned int   addr32[4];
53                 unsigned short addr16[8];
54                 unsigned char  addr[16];
55         }u;
56 };
57
58
59
60 struct net{
61         struct ip_addr ip;
62         struct ip_addr mask;
63 };
64
65 union sockaddr_union{
66                 struct sockaddr     s;
67                 struct sockaddr_in  sin;
68         #ifdef USE_IPV6
69                 struct sockaddr_in6 sin6;
70         #endif
71 };
72
73
74 struct socket_info{
75         int socket;
76         str name; /* name - eg.: foo.bar or 10.0.0.1 */
77         struct ip_addr address; /* ip address */
78         str address_str;        /* ip address converted to string -- optimization*/
79         unsigned short port_no;  /* port number */
80         str port_no_str; /* port number converted to string -- optimization*/
81         int is_ip; /* 1 if name is an ip address, 0 if not  -- optimization*/
82         int is_lo; /* 1 if is a loopback, 0 if not */
83         union sockaddr_union su; 
84         int proto; /* tcp or udp*/
85 };
86
87
88 /* len of the sockaddr */
89 #ifdef HAVE_SOCKADDR_SA_LEN
90 #define sockaddru_len(su)       ((su).s.sa_len)
91 #else
92 #ifdef USE_IPV6
93 #define sockaddru_len(su)       \
94                         (((su).s.sa_family==AF_INET6)?sizeof(struct sockaddr_in6):\
95                                         sizeof(struct sockaddr_in))
96 #else
97 #define sockaddru_len(su)       sizeof(struct sockaddr_in)
98 #endif /*USE_IPV6*/
99 #endif /* HAVE_SOCKADDR_SA_LEN*/
100         
101 /* inits an ip_addr with the addr. info from a hostent structure
102  * ip = struct ip_addr*
103  * he= struct hostent*
104  */
105 #define hostent2ip_addr(ip, he, addr_no) \
106         do{ \
107                 (ip)->af=(he)->h_addrtype; \
108                 (ip)->len=(he)->h_length;  \
109                 memcpy((ip)->u.addr, (he)->h_addr_list[(addr_no)], (ip)->len); \
110         }while(0)
111         
112
113
114
115 /* gets the protocol family corresponding to a specific address family
116  * ( PF_INET - AF_INET, PF_INET6 - AF_INET6, af for others)
117  */
118 #ifdef USE_IPV6
119 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:((af)==AF_INET6)?PF_INET6:(af))
120 #else
121 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:(af))
122 #endif
123
124
125
126
127 struct net* mk_net(struct ip_addr* ip, struct ip_addr* mask);
128 struct net* mk_net_bitlen(struct ip_addr* ip, unsigned int bitlen);
129
130 void print_ip(struct ip_addr* ip);
131 void stdout_print_ip(struct ip_addr* ip);
132 void print_net(struct net* net);
133
134
135
136
137 /* returns 1 if ip & net.mask == net.ip ; 0 otherwise & -1 on error 
138         [ diff. adress fams ]) */
139 inline static int matchnet(struct ip_addr* ip, struct net* net)
140 {
141         unsigned int r;
142         int ret;
143         
144         ret=-1;
145         if (ip->af == net->ip.af){
146                 for(r=0; r<ip->len/4; r++){ /* ipv4 & ipv6 addresses are
147                                                                            all multiple of 4*/
148                         if ((ip->u.addr32[r]&net->mask.u.addr32[r])!=
149                                                                                                                  net->ip.u.addr32[r]){
150                                 return 0;
151                         }
152                 }
153                 return 1;
154         };
155         return -1;
156 }
157
158
159
160
161 /* inits an ip_addr pointer from a sockaddr structure*/
162 static inline void sockaddr2ip_addr(struct ip_addr* ip, struct sockaddr* sa)
163 {
164         switch(sa->sa_family){
165         case AF_INET:
166                         ip->af=AF_INET;
167                         ip->len=4;
168                         memcpy(ip->u.addr, &((struct sockaddr_in*)sa)->sin_addr, 4);
169                         break;
170 #ifdef USE_IPV6
171         case AF_INET6:
172                         ip->af=AF_INET6;
173                         ip->len=16;
174                         memcpy(ip->u.addr, &((struct sockaddr_in6*)sa)->sin6_addr, 16);
175                         break;
176 #endif
177         default:
178                         LOG(L_CRIT, "sockaddr2ip_addr: BUG: unknown address family %d\n",
179                                         sa->sa_family);
180         }
181 }
182
183
184
185 /* compare 2 ip_addrs (both args are pointers)*/
186 #define ip_addr_cmp(ip1, ip2) \
187         (((ip1)->af==(ip2)->af)&& \
188                 (memcmp((ip1)->u.addr, (ip2)->u.addr, (ip1)->len)==0))
189
190
191
192 /* compare 2 sockaddr_unions */
193 static inline int su_cmp(union sockaddr_union* s1, union sockaddr_union* s2)
194 {
195         if (s1->s.sa_family!=s2->s.sa_family) return 0;
196         switch(s1->s.sa_family){
197                 case AF_INET:
198                         return (s1->sin.sin_port==s2->sin.sin_port)&&
199                                         (memcmp(&s1->sin.sin_addr, &s2->sin.sin_addr, 4)==0);
200                 case AF_INET6:
201                         return (s1->sin6.sin6_port==s2->sin6.sin6_port)&&
202                                         (memcmp(&s1->sin6.sin6_addr, &s2->sin6.sin6_addr, 16)==0);
203                 default:
204                         LOG(L_CRIT,"su_cmp: BUG: unknown address family %d\n",
205                                                 s1->s.sa_family);
206                         return 0;
207         }
208 }
209
210
211
212 /* gets the port number */
213 static inline short su_getport(union sockaddr_union* su)
214 {
215         switch(su->s.sa_family){
216                 case AF_INET:
217                         return su->sin.sin_port;
218                 case AF_INET6:
219                         return su->sin6.sin6_port;
220                 default:
221                         LOG(L_CRIT,"su_get_port: BUG: unknown address family %d\n",
222                                                 su->s.sa_family);
223                         return 0;
224         }
225 }
226
227
228
229 /* inits an ip_addr pointer from a sockaddr_union ip address */
230 static inline void su2ip_addr(struct ip_addr* ip, union sockaddr_union* su)
231 {
232         switch(su->s.sa_family){
233         case AF_INET: 
234                                         ip->af=AF_INET;
235                                         ip->len=4;
236                                         memcpy(ip->u.addr, &su->sin.sin_addr, 4);
237                                         break;
238 #ifdef USE_IPV6
239         case AF_INET6:
240                                         ip->af=AF_INET6;
241                                         ip->len=16;
242                                         memcpy(ip->u.addr, &su->sin6.sin6_addr, 16);
243                                         break;
244 #endif
245         default:
246                                         LOG(L_CRIT,"su2ip_addr: BUG: unknown address family %d\n",
247                                                         su->s.sa_family);
248         }
249 }
250
251
252 /* ip_addr2su -> the same as init_su*/
253 #define ip_addr2su init_su
254
255 /* inits a struct sockaddr_union from a struct ip_addr and a port no 
256  * returns 0 if ok, -1 on error (unknown address family) */
257 static inline int init_su( union sockaddr_union* su,
258                                                         struct ip_addr* ip,
259                                                         unsigned short   port ) 
260 {
261         memset(su, 0, sizeof(union sockaddr_union));/*needed on freebsd*/
262         su->s.sa_family=ip->af;
263         switch(ip->af){
264 #ifdef USE_IPV6
265         case    AF_INET6:
266                 memcpy(&su->sin6.sin6_addr, ip->u.addr, ip->len); 
267                 #ifdef HAVE_SOCKADDR_SA_LEN
268                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
269                 #endif
270                 su->sin6.sin6_port=port;
271                 break;
272 #endif
273         case AF_INET:
274                 memcpy(&su->sin.sin_addr, ip->u.addr, ip->len);
275                 #ifdef HAVE_SOCKADDR_SA_LEN
276                         su->sin.sin_len=sizeof(struct sockaddr_in);
277                 #endif
278                 su->sin.sin_port=port;
279                 break;
280         default:
281                 LOG(L_CRIT, "init_ss: BUG: unknown address family %d\n", ip->af);
282                 return -1;
283         }
284         return 0;
285 }
286
287
288
289 /* inits a struct sockaddr_union from a struct hostent, an address index in
290  * the hostent structure and a port no.
291  * WARNING: no index overflow  checks!
292  * returns 0 if ok, -1 on error (unknown address family) */
293 static inline int hostent2su( union sockaddr_union* su,
294                                                                 struct hostent* he,
295                                                                 unsigned int idx,
296                                                                 unsigned short   port ) 
297 {
298         memset(su, 0, sizeof(union sockaddr_union)); /*needed on freebsd*/
299         su->s.sa_family=he->h_addrtype;
300         switch(he->h_addrtype){
301 #ifdef USE_IPV6
302         case    AF_INET6:
303                 memcpy(&su->sin6.sin6_addr, he->h_addr_list[idx], he->h_length);
304                 #ifdef HAVE_SOCKADDR_SA_LEN
305                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
306                 #endif
307                 su->sin6.sin6_port=port;
308                 break;
309 #endif
310         case AF_INET:
311                 memcpy(&su->sin.sin_addr, he->h_addr_list[idx], he->h_length);
312                 #ifdef HAVE_SOCKADDR_SA_LEN
313                         su->sin.sin_len=sizeof(struct sockaddr_in);
314                 #endif
315                 su->sin.sin_port=port;
316                 break;
317         default:
318                 LOG(L_CRIT, "hostent2su: BUG: unknown address family %d\n", 
319                                 he->h_addrtype);
320                 return -1;
321         }
322         return 0;
323 }
324
325
326
327 /* fast ip_addr -> string convertor;
328  * it uses an internal buffer
329  */
330 static inline char* ip_addr2a(struct ip_addr* ip)
331 {
332
333         static char buff[40];/* 1234:5678:9012:3456:7890:1234:5678:9012\0 */
334         int offset;
335         register unsigned char a,b,c;
336 #ifdef USE_IPV6
337         register unsigned char d;
338         register unsigned short hex4;
339 #endif
340         int r;
341         #define HEXDIG(x) (((x)>=10)?(x)-10+'A':(x)+'0')
342         
343         
344         offset=0;
345         switch(ip->af){
346         #ifdef USE_IPV6
347                 case AF_INET6:
348                         for(r=0;r<7;r++){
349                                 hex4=ntohs(ip->u.addr16[r]);
350                                 a=hex4>>12;
351                                 b=(hex4>>8)&0xf;
352                                 c=(hex4>>4)&0xf;
353                                 d=hex4&0xf;
354                                 if (a){
355                                         buff[offset]=HEXDIG(a);
356                                         buff[offset+1]=HEXDIG(b);
357                                         buff[offset+2]=HEXDIG(c);
358                                         buff[offset+3]=HEXDIG(d);
359                                         buff[offset+4]=':';
360                                         offset+=5;
361                                 }else if(b){
362                                         buff[offset]=HEXDIG(b);
363                                         buff[offset+1]=HEXDIG(c);
364                                         buff[offset+2]=HEXDIG(d);
365                                         buff[offset+3]=':';
366                                         offset+=4;
367                                 }else if(c){
368                                         buff[offset]=HEXDIG(c);
369                                         buff[offset+1]=HEXDIG(d);
370                                         buff[offset+2]=':';
371                                         offset+=3;
372                                 }else{
373                                         buff[offset]=HEXDIG(d);
374                                         buff[offset+1]=':';
375                                         offset+=2;
376                                 }
377                         }
378                         /* last int16*/
379                         hex4=ntohs(ip->u.addr16[r]);
380                         a=hex4>>12;
381                         b=(hex4>>8)&0xf;
382                         c=(hex4>>4)&0xf;
383                         d=hex4&0xf;
384                         if (a){
385                                 buff[offset]=HEXDIG(a);
386                                 buff[offset+1]=HEXDIG(b);
387                                 buff[offset+2]=HEXDIG(c);
388                                 buff[offset+3]=HEXDIG(d);
389                                 buff[offset+4]=0;
390                         }else if(b){
391                                 buff[offset]=HEXDIG(b);
392                                 buff[offset+1]=HEXDIG(c);
393                                 buff[offset+2]=HEXDIG(d);
394                                 buff[offset+3]=0;
395                         }else if(c){
396                                 buff[offset]=HEXDIG(c);
397                                 buff[offset+1]=HEXDIG(d);
398                                 buff[offset+2]=0;
399                         }else{
400                                 buff[offset]=HEXDIG(d);
401                                 buff[offset+1]=0;
402                         }
403                         break;
404         #endif
405                 case AF_INET:
406                         for(r=0;r<3;r++){
407                                 a=ip->u.addr[r]/100;
408                                 c=ip->u.addr[r]%10;
409                                 b=ip->u.addr[r]%100/10;
410                                 if (a){
411                                         buff[offset]=a+'0';
412                                         buff[offset+1]=b+'0';
413                                         buff[offset+2]=c+'0';
414                                         buff[offset+3]='.';
415                                         offset+=4;
416                                 }else if (b){
417                                         buff[offset]=b+'0';
418                                         buff[offset+1]=c+'0';
419                                         buff[offset+2]='.';
420                                         offset+=3;
421                                 }else{
422                                         buff[offset]=c+'0';
423                                         buff[offset+1]='.';
424                                         offset+=2;
425                                 }
426                         }
427                         /* last number */
428                         a=ip->u.addr[r]/100;
429                         c=ip->u.addr[r]%10;
430                         b=ip->u.addr[r]%100/10;
431                         if (a){
432                                 buff[offset]=a+'0';
433                                 buff[offset+1]=b+'0';
434                                 buff[offset+2]=c+'0';
435                                 buff[offset+3]=0;
436                         }else if (b){
437                                 buff[offset]=b+'0';
438                                 buff[offset+1]=c+'0';
439                                 buff[offset+2]=0;
440                         }else{
441                                 buff[offset]=c+'0';
442                                 buff[offset+1]=0;
443                         }
444                         break;
445                 
446                 default:
447                         LOG(L_CRIT, "BUG: ip_addr2a: unknown address family %d\n",
448                                         ip->af);
449                         return 0;
450         }
451         
452         return buff;
453 }
454
455
456
457 /* converts an ip_addr structure to a hostent, returns pointer to internal
458  * statical structure */
459 static inline struct hostent* ip_addr2he(char* name, int len,
460                                                                                         struct ip_addr* ip)
461 {
462         static struct hostent he;
463         static char hostname[256];
464         static char* p_aliases[1];
465         static char* p_addr[2];
466         static char address[16];
467         
468         p_aliases[0]=0; /* no aliases*/
469         p_addr[1]=0; /* only one address*/
470         p_addr[0]=address;
471         strncpy(hostname, name, (len<256)?len+1:256);
472         if (ip->len>16) return 0;
473         memcpy(address, ip->u.addr, ip->len);
474         
475         he.h_addrtype=ip->af;
476         he.h_length=ip->len;
477         he.h_addr_list=p_addr;
478         he.h_aliases=p_aliases;
479         he.h_name=hostname;
480         return &he;
481 }
482 #endif