- ipv6 support (-DUSE_IPV6)
[sip-router] / ip_addr.h
1 /* $Id$
2  *
3  * ip address family realted structures
4  */
5
6 #ifndef ip_addr_h
7 #define ip_addr_h
8
9 #include <string.h>
10 #include <netinet/in.h>
11 #include <netdb.h>
12
13 #ifdef USE_IPV6
14         #ifdef FreeBSD                  /* freebsd is brain damaged and needs a different
15                                                            include */
16 #include <netinet6/in6.h>
17         #endif
18 #endif
19
20 #include "dprint.h"
21
22
23
24 struct ip_addr{
25         unsigned int af; /* address family: AF_INET6 or AF_INET */
26         unsigned int len;    /* address len, 16 or 4 */
27         
28         /* 64 bits alligned address */
29         union {
30                 unsigned int   addr32[4];
31                 unsigned short addr16[8];
32                 unsigned char  addr[16];
33         }u;
34 };
35
36
37
38 struct net{
39         struct ip_addr ip;
40         struct ip_addr mask;
41 };
42
43 union sockaddr_union{
44                 struct sockaddr     s;
45                 struct sockaddr_in  sin;
46         #ifdef USE_IPV6
47                 struct sockaddr_in6 sin6;
48         #endif
49 };
50
51
52
53
54 /* inits an ip_addr with the addr. info from a hostent structure
55  * ip = struct ip_addr*
56  * he= struct hostent*
57  */
58 #define hostent2ip_addr(ip, he, addr_no) \
59         do{ \
60                 (ip)->af=(he)->h_addrtype; \
61                 (ip)->len=(he)->h_length;  \
62                 memcpy((ip)->u.addr, (he)->h_addr_list[(addr_no)], (ip)->len); \
63         }while(0)
64         
65
66
67
68 /* gets the protocol family corresponding to a specific address family
69  * ( PF_INET - AF_INET, PF_INET6 - AF_INET6, af for others)
70  */
71 #ifdef USE_IPV6
72 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:((af)==AF_INET6)?PF_INET6:(af))
73 #else
74 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:(af))
75 #endif
76
77
78
79
80 struct net* mk_net(struct ip_addr* ip, struct ip_addr* mask);
81 struct net* mk_net_bitlen(struct ip_addr* ip, unsigned int bitlen);
82
83 void print_ip(struct ip_addr* ip);
84 void stdout_print_ip(struct ip_addr* ip);
85 void print_net(struct net* net);
86
87
88
89
90 /* returns 1 if ip & net.mask == net.ip ; 0 otherwise & -1 on error 
91         [ diff. adress fams ]) */
92 inline static int matchnet(struct ip_addr* ip, struct net* net)
93 {
94         int r;
95         int ret;
96         
97         ret=-1;
98         if (ip->af == net->ip.af){
99                 for(r=0; r<ip->len/4; r++){ /* ipv4 & ipv6 addresses are
100                                                                            all multiple of 4*/
101                         if ((ip->u.addr32[r]&net->mask.u.addr32[r])!=
102                                                                                                                  net->ip.u.addr32[r]){
103                                 return 0;
104                         }
105                 }
106                 return 1;
107         };
108         return -1;
109 }
110
111
112
113 /* inits an ip_addr pointer from a sockaddr_union ip address */
114 static inline void su2ip_addr(struct ip_addr* ip, union sockaddr_union* su)
115 {
116         switch(su->s.sa_family){
117         case AF_INET: 
118                                         ip->af=AF_INET;
119                                         ip->len=4;
120                                         memcpy(ip->u.addr, &su->sin.sin_addr, 4);
121                                         break;
122 #ifdef USE_IPV6
123         case AF_INET6:
124                                         ip->af=AF_INET6;
125                                         ip->len=16;
126                                         memcpy(ip->u.addr, &su->sin6.sin6_addr, 16);
127                                         break;
128 #endif
129         default:
130                                         LOG(L_CRIT,"su2ip_addr: BUG: unknown address family %d\n",
131                                                         su->s.sa_family);
132         }
133 }
134
135
136
137 /* inits a struct sockaddr_union from a struct ip_addr and a port no 
138  * returns 0 if ok, -1 on error (unknown address family) */
139 static inline int init_su( union sockaddr_union* su,
140                                                         struct ip_addr* ip,
141                                                         unsigned short   port ) 
142 {
143         su->s.sa_family=ip->af;
144         switch(ip->af){
145 #ifdef USE_IPV6
146         case    AF_INET6:
147                 memcpy(&su->sin6.sin6_addr, ip->u.addr, ip->len); 
148                 #ifdef FreeBSD
149                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
150                 #endif
151                 su->sin6.sin6_port=port;
152                 break;
153 #endif
154         case AF_INET:
155                 memcpy(&su->sin.sin_addr, ip->u.addr, ip->len);
156                 #ifdef FreeBSD
157                         su->sin.sin_len=sizeof(struct sockaddr_in);
158                 #endif
159                 su->sin.sin_port=port;
160                 break;
161         default:
162                 LOG(L_CRIT, "init_ss: BUG: unknown address family %d\n", ip->af);
163                 return -1;
164         }
165         return 0;
166 }
167
168
169
170 /* inits a struct sockaddr_union from a struct hostent, an address index int
171  * the hostent structure and a port no.
172  * WARNING: no index overflow  checks!
173  * returns 0 if ok, -1 on error (unknown address family) */
174 static inline int hostent2su( union sockaddr_union* su,
175                                                                 struct hostent* he,
176                                                                 unsigned int idx,
177                                                                 unsigned short   port ) 
178 {
179         su->s.sa_family=he->h_addrtype;
180         switch(he->h_addrtype){
181 #ifdef USE_IPV6
182         case    AF_INET6:
183                 memcpy(&su->sin6.sin6_addr, he->h_addr_list[idx], he->h_length);
184                 #ifdef FreeBSD
185                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
186                 #endif
187                 su->sin6.sin6_port=port;
188                 break;
189 #endif
190         case AF_INET:
191                 memcpy(&su->sin.sin_addr, he->h_addr_list[idx], he->h_length);
192                 #ifdef FreeBSD
193                         su->sin.sin_len=sizeof(struct sockaddr_in);
194                 #endif
195                 su->sin.sin_port=port;
196                 break;
197         default:
198                 LOG(L_CRIT, "hostent2su: BUG: unknown address family %d\n", 
199                                 he->h_addrtype);
200                 return -1;
201         }
202         return 0;
203 }
204
205
206
207 /* fast ip_addr -> string convertor;
208  * it uses an internal buffer
209  */
210 static inline char* ip_addr2a(struct ip_addr* ip)
211 {
212
213         static char buff[40];/* 1234:5678:9012:3456:7890:1234:5678:9012\0 */
214         int offset;
215         register unsigned char a,b,c;
216 #ifdef USE_IPV6
217         register unsigned char d;
218 #endif
219         int r;
220         #define HEXDIG(x) (((x)>=10)?(x)-10+'A':(x)+'0')
221         
222         
223         offset=0;
224         switch(ip->af){
225         #ifdef USE_IPV6
226                 case AF_INET6:
227                         for(r=0;r<7;r++){
228                                 a=ip->u.addr16[r]>>12;
229                                 b=(ip->u.addr16[r]>>8)&0xf;
230                                 c=(ip->u.addr16[r]>>4)&0xf;
231                                 d=ip->u.addr16[r]&0xf;
232                                 if (a){
233                                         buff[offset]=HEXDIG(a);
234                                         buff[offset+1]=HEXDIG(b);
235                                         buff[offset+2]=HEXDIG(c);
236                                         buff[offset+3]=HEXDIG(d);
237                                         buff[offset+4]=':';
238                                         offset+=5;
239                                 }else if(b){
240                                         buff[offset]=HEXDIG(b);
241                                         buff[offset+1]=HEXDIG(c);
242                                         buff[offset+2]=HEXDIG(d);
243                                         buff[offset+3]=':';
244                                         offset+=4;
245                                 }else if(c){
246                                         buff[offset]=HEXDIG(c);
247                                         buff[offset+1]=HEXDIG(d);
248                                         buff[offset+2]=':';
249                                         offset+=3;
250                                 }else{
251                                         buff[offset]=HEXDIG(d);
252                                         buff[offset+1]=':';
253                                         offset+=2;
254                                 }
255                         }
256                         /* last int16*/
257                         a=ip->u.addr16[r]>>12;
258                         b=(ip->u.addr16[r]>>8)&0xf;
259                         c=(ip->u.addr16[r]>>4)&0xf;
260                         d=ip->u.addr16[r]&0xf;
261                         if (a){
262                                 buff[offset]=HEXDIG(a);
263                                 buff[offset+1]=HEXDIG(b);
264                                 buff[offset+2]=HEXDIG(c);
265                                 buff[offset+3]=HEXDIG(d);
266                                 buff[offset+4]=0;
267                         }else if(b){
268                                 buff[offset]=HEXDIG(b);
269                                 buff[offset+1]=HEXDIG(c);
270                                 buff[offset+2]=HEXDIG(d);
271                                 buff[offset+3]=0;
272                         }else if(c){
273                                 buff[offset]=HEXDIG(c);
274                                 buff[offset+1]=HEXDIG(d);
275                                 buff[offset+2]=0;
276                         }else{
277                                 buff[offset]=HEXDIG(d);
278                                 buff[offset+1]=0;
279                         }
280                         break;
281         #endif
282                 case AF_INET:
283                         for(r=0;r<3;r++){
284                                 a=ip->u.addr[r]/100;
285                                 c=ip->u.addr[r]%10;
286                                 b=ip->u.addr[r]%100/10;
287                                 if (a){
288                                         buff[offset]=a+'0';
289                                         buff[offset+1]=b+'0';
290                                         buff[offset+2]=c+'0';
291                                         buff[offset+3]='.';
292                                         offset+=4;
293                                 }else if (b){
294                                         buff[offset]=b+'0';
295                                         buff[offset+1]=c+'0';
296                                         buff[offset+2]='.';
297                                         offset+=3;
298                                 }else{
299                                         buff[offset]=c+'0';
300                                         buff[offset+1]='.';
301                                         offset+=2;
302                                 }
303                         }
304                         /* last number */
305                         a=ip->u.addr[r]/100;
306                         c=ip->u.addr[r]%10;
307                         b=ip->u.addr[r]%100/10;
308                         if (a){
309                                 buff[offset]=a+'0';
310                                 buff[offset+1]=b+'0';
311                                 buff[offset+2]=c+'0';
312                                 buff[offset+3]=0;
313                         }else if (b){
314                                 buff[offset]=b+'0';
315                                 buff[offset+1]=c+'0';
316                                 buff[offset+2]=0;
317                         }else{
318                                 buff[offset]=c+'0';
319                                 buff[offset+1]=0;
320                         }
321                         break;
322                 
323                 default:
324                         LOG(L_CRIT, "BUG: ip_addr2a: unknown address family %d\n",
325                                         ip->af);
326                         return 0;
327         }
328         
329         return buff;
330 }
331
332
333
334
335
336 #endif