- more tcp stuff (uses locking.h, hashtables, mostly untested)
[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 enum sip_protos { PROTO_UDP, PROTO_TCP, PROTO_TLS };
44
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 long  addrl[16/sizeof(long)]; /* long format*/
53                 unsigned int   addr32[4];
54                 unsigned short addr16[8];
55                 unsigned char  addr[16];
56         }u;
57 };
58
59
60
61 struct net{
62         struct ip_addr ip;
63         struct ip_addr mask;
64 };
65
66 union sockaddr_union{
67                 struct sockaddr     s;
68                 struct sockaddr_in  sin;
69         #ifdef USE_IPV6
70                 struct sockaddr_in6 sin6;
71         #endif
72 };
73
74
75 struct socket_info{
76         int socket;
77         str name; /* name - eg.: foo.bar or 10.0.0.1 */
78         struct ip_addr address; /* ip address */
79         str address_str;        /* ip address converted to string -- optimization*/
80         unsigned short port_no;  /* port number */
81         str port_no_str; /* port number converted to string -- optimization*/
82         int is_ip; /* 1 if name is an ip address, 0 if not  -- optimization*/
83         int is_lo; /* 1 if is a loopback, 0 if not */
84         union sockaddr_union su; 
85         int proto; /* tcp or udp*/
86 };
87
88
89 struct receive_info{
90         struct ip_addr src_ip;
91         struct ip_addr dst_ip;
92         short src_port;
93         short dst_port;
94         int proto;
95         int proto_reserved1;
96         int proto_reserved2;
97         union sockaddr_union src_su; /* usefull for replies*/
98         struct socket_info* bind_address; /* sock_info structure on which 
99                                                                           the msg was received*/
100         /* no need for dst_su yet */
101 };
102
103
104 /* len of the sockaddr */
105 #ifdef HAVE_SOCKADDR_SA_LEN
106 #define sockaddru_len(su)       ((su).s.sa_len)
107 #else
108 #ifdef USE_IPV6
109 #define sockaddru_len(su)       \
110                         (((su).s.sa_family==AF_INET6)?sizeof(struct sockaddr_in6):\
111                                         sizeof(struct sockaddr_in))
112 #else
113 #define sockaddru_len(su)       sizeof(struct sockaddr_in)
114 #endif /*USE_IPV6*/
115 #endif /* HAVE_SOCKADDR_SA_LEN*/
116         
117 /* inits an ip_addr with the addr. info from a hostent structure
118  * ip = struct ip_addr*
119  * he= struct hostent*
120  */
121 #define hostent2ip_addr(ip, he, addr_no) \
122         do{ \
123                 (ip)->af=(he)->h_addrtype; \
124                 (ip)->len=(he)->h_length;  \
125                 memcpy((ip)->u.addr, (he)->h_addr_list[(addr_no)], (ip)->len); \
126         }while(0)
127         
128
129
130
131 /* gets the protocol family corresponding to a specific address family
132  * ( PF_INET - AF_INET, PF_INET6 - AF_INET6, af for others)
133  */
134 #ifdef USE_IPV6
135 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:((af)==AF_INET6)?PF_INET6:(af))
136 #else
137 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:(af))
138 #endif
139
140
141
142
143 struct net* mk_net(struct ip_addr* ip, struct ip_addr* mask);
144 struct net* mk_net_bitlen(struct ip_addr* ip, unsigned int bitlen);
145
146 void print_ip(struct ip_addr* ip);
147 void stdout_print_ip(struct ip_addr* ip);
148 void print_net(struct net* net);
149
150
151
152
153 /* returns 1 if ip & net.mask == net.ip ; 0 otherwise & -1 on error 
154         [ diff. adress fams ]) */
155 inline static int matchnet(struct ip_addr* ip, struct net* net)
156 {
157         unsigned int r;
158         int ret;
159         
160         ret=-1;
161         if (ip->af == net->ip.af){
162                 for(r=0; r<ip->len/4; r++){ /* ipv4 & ipv6 addresses are
163                                                                            all multiple of 4*/
164                         if ((ip->u.addr32[r]&net->mask.u.addr32[r])!=
165                                                                                                                  net->ip.u.addr32[r]){
166                                 return 0;
167                         }
168                 }
169                 return 1;
170         };
171         return -1;
172 }
173
174
175
176
177 /* inits an ip_addr pointer from a sockaddr structure*/
178 static inline void sockaddr2ip_addr(struct ip_addr* ip, struct sockaddr* sa)
179 {
180         switch(sa->sa_family){
181         case AF_INET:
182                         ip->af=AF_INET;
183                         ip->len=4;
184                         memcpy(ip->u.addr, &((struct sockaddr_in*)sa)->sin_addr, 4);
185                         break;
186 #ifdef USE_IPV6
187         case AF_INET6:
188                         ip->af=AF_INET6;
189                         ip->len=16;
190                         memcpy(ip->u.addr, &((struct sockaddr_in6*)sa)->sin6_addr, 16);
191                         break;
192 #endif
193         default:
194                         LOG(L_CRIT, "sockaddr2ip_addr: BUG: unknown address family %d\n",
195                                         sa->sa_family);
196         }
197 }
198
199
200
201 /* compare 2 ip_addrs (both args are pointers)*/
202 #define ip_addr_cmp(ip1, ip2) \
203         (((ip1)->af==(ip2)->af)&& \
204                 (memcmp((ip1)->u.addr, (ip2)->u.addr, (ip1)->len)==0))
205
206
207
208 /* compare 2 sockaddr_unions */
209 static inline int su_cmp(union sockaddr_union* s1, union sockaddr_union* s2)
210 {
211         if (s1->s.sa_family!=s2->s.sa_family) return 0;
212         switch(s1->s.sa_family){
213                 case AF_INET:
214                         return (s1->sin.sin_port==s2->sin.sin_port)&&
215                                         (memcmp(&s1->sin.sin_addr, &s2->sin.sin_addr, 4)==0);
216 #ifdef USE_IPV6
217                 case AF_INET6:
218                         return (s1->sin6.sin6_port==s2->sin6.sin6_port)&&
219                                         (memcmp(&s1->sin6.sin6_addr, &s2->sin6.sin6_addr, 16)==0);
220 #endif
221                 default:
222                         LOG(L_CRIT,"su_cmp: BUG: unknown address family %d\n",
223                                                 s1->s.sa_family);
224                         return 0;
225         }
226 }
227
228
229
230 /* gets the port number */
231 static inline short su_getport(union sockaddr_union* su)
232 {
233         switch(su->s.sa_family){
234                 case AF_INET:
235                         return su->sin.sin_port;
236 #ifdef USE_IPV6
237                 case AF_INET6:
238                         return su->sin6.sin6_port;
239 #endif
240                 default:
241                         LOG(L_CRIT,"su_get_port: BUG: unknown address family %d\n",
242                                                 su->s.sa_family);
243                         return 0;
244         }
245 }
246
247
248
249 /* inits an ip_addr pointer from a sockaddr_union ip address */
250 static inline void su2ip_addr(struct ip_addr* ip, union sockaddr_union* su)
251 {
252         switch(su->s.sa_family){
253         case AF_INET: 
254                                         ip->af=AF_INET;
255                                         ip->len=4;
256                                         memcpy(ip->u.addr, &su->sin.sin_addr, 4);
257                                         break;
258 #ifdef USE_IPV6
259         case AF_INET6:
260                                         ip->af=AF_INET6;
261                                         ip->len=16;
262                                         memcpy(ip->u.addr, &su->sin6.sin6_addr, 16);
263                                         break;
264 #endif
265         default:
266                                         LOG(L_CRIT,"su2ip_addr: BUG: unknown address family %d\n",
267                                                         su->s.sa_family);
268         }
269 }
270
271
272 /* ip_addr2su -> the same as init_su*/
273 #define ip_addr2su init_su
274
275 /* inits a struct sockaddr_union from a struct ip_addr and a port no 
276  * returns 0 if ok, -1 on error (unknown address family) */
277 static inline int init_su( union sockaddr_union* su,
278                                                         struct ip_addr* ip,
279                                                         unsigned short   port ) 
280 {
281         memset(su, 0, sizeof(union sockaddr_union));/*needed on freebsd*/
282         su->s.sa_family=ip->af;
283         switch(ip->af){
284 #ifdef USE_IPV6
285         case    AF_INET6:
286                 memcpy(&su->sin6.sin6_addr, ip->u.addr, ip->len); 
287                 #ifdef HAVE_SOCKADDR_SA_LEN
288                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
289                 #endif
290                 su->sin6.sin6_port=port;
291                 break;
292 #endif
293         case AF_INET:
294                 memcpy(&su->sin.sin_addr, ip->u.addr, ip->len);
295                 #ifdef HAVE_SOCKADDR_SA_LEN
296                         su->sin.sin_len=sizeof(struct sockaddr_in);
297                 #endif
298                 su->sin.sin_port=port;
299                 break;
300         default:
301                 LOG(L_CRIT, "init_ss: BUG: unknown address family %d\n", ip->af);
302                 return -1;
303         }
304         return 0;
305 }
306
307
308
309 /* inits a struct sockaddr_union from a struct hostent, an address index in
310  * the hostent structure and a port no.
311  * WARNING: no index overflow  checks!
312  * returns 0 if ok, -1 on error (unknown address family) */
313 static inline int hostent2su( union sockaddr_union* su,
314                                                                 struct hostent* he,
315                                                                 unsigned int idx,
316                                                                 unsigned short   port ) 
317 {
318         memset(su, 0, sizeof(union sockaddr_union)); /*needed on freebsd*/
319         su->s.sa_family=he->h_addrtype;
320         switch(he->h_addrtype){
321 #ifdef USE_IPV6
322         case    AF_INET6:
323                 memcpy(&su->sin6.sin6_addr, he->h_addr_list[idx], he->h_length);
324                 #ifdef HAVE_SOCKADDR_SA_LEN
325                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
326                 #endif
327                 su->sin6.sin6_port=port;
328                 break;
329 #endif
330         case AF_INET:
331                 memcpy(&su->sin.sin_addr, he->h_addr_list[idx], he->h_length);
332                 #ifdef HAVE_SOCKADDR_SA_LEN
333                         su->sin.sin_len=sizeof(struct sockaddr_in);
334                 #endif
335                 su->sin.sin_port=port;
336                 break;
337         default:
338                 LOG(L_CRIT, "hostent2su: BUG: unknown address family %d\n", 
339                                 he->h_addrtype);
340                 return -1;
341         }
342         return 0;
343 }
344
345
346
347 /* fast ip_addr -> string convertor;
348  * it uses an internal buffer
349  */
350 static inline char* ip_addr2a(struct ip_addr* ip)
351 {
352
353         static char buff[40];/* 1234:5678:9012:3456:7890:1234:5678:9012\0 */
354         int offset;
355         register unsigned char a,b,c;
356 #ifdef USE_IPV6
357         register unsigned char d;
358         register unsigned short hex4;
359 #endif
360         int r;
361         #define HEXDIG(x) (((x)>=10)?(x)-10+'A':(x)+'0')
362         
363         
364         offset=0;
365         switch(ip->af){
366         #ifdef USE_IPV6
367                 case AF_INET6:
368                         for(r=0;r<7;r++){
369                                 hex4=ntohs(ip->u.addr16[r]);
370                                 a=hex4>>12;
371                                 b=(hex4>>8)&0xf;
372                                 c=(hex4>>4)&0xf;
373                                 d=hex4&0xf;
374                                 if (a){
375                                         buff[offset]=HEXDIG(a);
376                                         buff[offset+1]=HEXDIG(b);
377                                         buff[offset+2]=HEXDIG(c);
378                                         buff[offset+3]=HEXDIG(d);
379                                         buff[offset+4]=':';
380                                         offset+=5;
381                                 }else if(b){
382                                         buff[offset]=HEXDIG(b);
383                                         buff[offset+1]=HEXDIG(c);
384                                         buff[offset+2]=HEXDIG(d);
385                                         buff[offset+3]=':';
386                                         offset+=4;
387                                 }else if(c){
388                                         buff[offset]=HEXDIG(c);
389                                         buff[offset+1]=HEXDIG(d);
390                                         buff[offset+2]=':';
391                                         offset+=3;
392                                 }else{
393                                         buff[offset]=HEXDIG(d);
394                                         buff[offset+1]=':';
395                                         offset+=2;
396                                 }
397                         }
398                         /* last int16*/
399                         hex4=ntohs(ip->u.addr16[r]);
400                         a=hex4>>12;
401                         b=(hex4>>8)&0xf;
402                         c=(hex4>>4)&0xf;
403                         d=hex4&0xf;
404                         if (a){
405                                 buff[offset]=HEXDIG(a);
406                                 buff[offset+1]=HEXDIG(b);
407                                 buff[offset+2]=HEXDIG(c);
408                                 buff[offset+3]=HEXDIG(d);
409                                 buff[offset+4]=0;
410                         }else if(b){
411                                 buff[offset]=HEXDIG(b);
412                                 buff[offset+1]=HEXDIG(c);
413                                 buff[offset+2]=HEXDIG(d);
414                                 buff[offset+3]=0;
415                         }else if(c){
416                                 buff[offset]=HEXDIG(c);
417                                 buff[offset+1]=HEXDIG(d);
418                                 buff[offset+2]=0;
419                         }else{
420                                 buff[offset]=HEXDIG(d);
421                                 buff[offset+1]=0;
422                         }
423                         break;
424         #endif
425                 case AF_INET:
426                         for(r=0;r<3;r++){
427                                 a=ip->u.addr[r]/100;
428                                 c=ip->u.addr[r]%10;
429                                 b=ip->u.addr[r]%100/10;
430                                 if (a){
431                                         buff[offset]=a+'0';
432                                         buff[offset+1]=b+'0';
433                                         buff[offset+2]=c+'0';
434                                         buff[offset+3]='.';
435                                         offset+=4;
436                                 }else if (b){
437                                         buff[offset]=b+'0';
438                                         buff[offset+1]=c+'0';
439                                         buff[offset+2]='.';
440                                         offset+=3;
441                                 }else{
442                                         buff[offset]=c+'0';
443                                         buff[offset+1]='.';
444                                         offset+=2;
445                                 }
446                         }
447                         /* last number */
448                         a=ip->u.addr[r]/100;
449                         c=ip->u.addr[r]%10;
450                         b=ip->u.addr[r]%100/10;
451                         if (a){
452                                 buff[offset]=a+'0';
453                                 buff[offset+1]=b+'0';
454                                 buff[offset+2]=c+'0';
455                                 buff[offset+3]=0;
456                         }else if (b){
457                                 buff[offset]=b+'0';
458                                 buff[offset+1]=c+'0';
459                                 buff[offset+2]=0;
460                         }else{
461                                 buff[offset]=c+'0';
462                                 buff[offset+1]=0;
463                         }
464                         break;
465                 
466                 default:
467                         LOG(L_CRIT, "BUG: ip_addr2a: unknown address family %d\n",
468                                         ip->af);
469                         return 0;
470         }
471         
472         return buff;
473 }
474
475
476
477 /* converts an ip_addr structure to a hostent, returns pointer to internal
478  * statical structure */
479 static inline struct hostent* ip_addr2he(str* name, struct ip_addr* ip)
480 {
481         static struct hostent he;
482         static char hostname[256];
483         static char* p_aliases[1];
484         static char* p_addr[2];
485         static char address[16];
486         
487         p_aliases[0]=0; /* no aliases*/
488         p_addr[1]=0; /* only one address*/
489         p_addr[0]=address;
490         strncpy(hostname, name->s, (name->len<256)?(name->len)+1:256);
491         if (ip->len>16) return 0;
492         memcpy(address, ip->u.addr, ip->len);
493         
494         he.h_addrtype=ip->af;
495         he.h_length=ip->len;
496         he.h_addr_list=p_addr;
497         he.h_aliases=p_aliases;
498         he.h_name=hostname;
499         return &he;
500 }
501 #endif