a5b16980fec24afa3f7df53d69be64975710f5b2
[sip-router] / ip_addr.h
1 /* $Id$
2  *
3  * ip address family related 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  * History:
30  * --------
31  *  2003-02-13  added struct dest_info (andrei)
32  *  2003-04-06  all ports are stored/passed in host byte order now (andrei)
33  *  2006-04-20  comp support in recv_info and dest_info (andrei)
34  *  2006-04-21  added init_dst_from_rcv (andrei)
35  */
36
37 #ifndef ip_addr_h
38 #define ip_addr_h
39
40 #include <string.h>
41 #include <sys/types.h>
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <netdb.h>
45 #include "str.h"
46
47
48 #include "dprint.h"
49
50 enum sip_protos { PROTO_NONE, PROTO_UDP, PROTO_TCP, PROTO_TLS, PROTO_SCTP };
51 #ifdef USE_COMP
52 enum comp_methods { COMP_NONE, COMP_SIGCOMP, COMP_SERGZ };
53 #endif
54
55 struct ip_addr{
56         unsigned int af; /* address family: AF_INET6 or AF_INET */
57         unsigned int len;    /* address len, 16 or 4 */
58         
59         /* 64 bits aligned address */
60         union {
61                 unsigned long  addrl[16/sizeof(long)]; /* long format*/
62                 unsigned int   addr32[4];
63                 unsigned short addr16[8];
64                 unsigned char  addr[16];
65         }u;
66 };
67
68
69
70 struct net{
71         struct ip_addr ip;
72         struct ip_addr mask;
73 };
74
75 union sockaddr_union{
76                 struct sockaddr     s;
77                 struct sockaddr_in  sin;
78         #ifdef USE_IPV6
79                 struct sockaddr_in6 sin6;
80         #endif
81 };
82
83
84
85 enum si_flags { SI_NONE=0, SI_IS_IP=1, SI_IS_LO=2, SI_IS_MCAST=4 };
86
87 struct socket_info{
88         int socket;
89         str name; /* name - eg.: foo.bar or 10.0.0.1 */
90         struct ip_addr address; /* ip address */
91         str address_str;        /* ip address converted to string -- optimization*/
92         str port_no_str; /* port number converted to string -- optimization*/
93         enum si_flags flags; /* SI_IS_IP | SI_IS_LO | SI_IS_MCAST */
94         union sockaddr_union su; 
95         struct socket_info* next;
96         struct socket_info* prev;
97         unsigned short port_no;  /* port number */
98         char proto; /* tcp or udp*/
99 };
100
101
102 struct receive_info{
103         struct ip_addr src_ip;
104         struct ip_addr dst_ip;
105         unsigned short src_port; /* host byte order */
106         unsigned short dst_port; /* host byte order */
107         int proto_reserved1; /* tcp stores the connection id here */
108         int proto_reserved2;
109         union sockaddr_union src_su; /* useful for replies*/
110         struct socket_info* bind_address; /* sock_info structure on which 
111                                                                           the msg was received*/
112         char proto;
113 #ifdef USE_COMP
114         short comp; /* compression */
115 #endif
116         /* no need for dst_su yet */
117 };
118
119
120 struct dest_info{
121         struct socket_info* send_sock;
122         union sockaddr_union to;
123         int id; /* tcp stores the connection id here */ 
124         char proto;
125 #ifdef USE_COMP
126         short comp;
127 #endif
128 };
129
130
131 struct socket_id{
132         char* name;
133         int proto;
134         int port;
135         struct socket_id* next;
136 };
137
138
139
140 /* len of the sockaddr */
141 #ifdef HAVE_SOCKADDR_SA_LEN
142 #define sockaddru_len(su)       ((su).s.sa_len)
143 #else
144 #ifdef USE_IPV6
145 #define sockaddru_len(su)       \
146                         (((su).s.sa_family==AF_INET6)?sizeof(struct sockaddr_in6):\
147                                         sizeof(struct sockaddr_in))
148 #else
149 #define sockaddru_len(su)       sizeof(struct sockaddr_in)
150 #endif /*USE_IPV6*/
151 #endif /* HAVE_SOCKADDR_SA_LEN*/
152         
153 /* inits an ip_addr with the addr. info from a hostent structure
154  * ip = struct ip_addr*
155  * he= struct hostent*
156  */
157 #define hostent2ip_addr(ip, he, addr_no) \
158         do{ \
159                 (ip)->af=(he)->h_addrtype; \
160                 (ip)->len=(he)->h_length;  \
161                 memcpy((ip)->u.addr, (he)->h_addr_list[(addr_no)], (ip)->len); \
162         }while(0)
163         
164
165
166
167 /* gets the protocol family corresponding to a specific address family
168  * ( PF_INET - AF_INET, PF_INET6 - AF_INET6, af for others)
169  */
170 #ifdef USE_IPV6
171 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:((af)==AF_INET6)?PF_INET6:(af))
172 #else
173 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:(af))
174 #endif
175
176
177
178
179 struct net* mk_net(struct ip_addr* ip, struct ip_addr* mask);
180 struct net* mk_net_bitlen(struct ip_addr* ip, unsigned int bitlen);
181
182 void print_ip(char* prefix, struct ip_addr* ip, char* suffix);
183 void stdout_print_ip(struct ip_addr* ip);
184 void print_net(struct net* net);
185
186 #ifdef USE_MCAST
187 /* Returns 1 if the given address is a multicast address */
188 int is_mcast(struct ip_addr* ip);
189 #endif /* USE_MCAST */
190
191 /* returns 1 if the given ip address is INADDR_ANY or IN6ADDR_ANY,
192  * 0 otherwise */
193 inline static int ip_addr_any(struct ip_addr* ip)
194 {
195         int r;
196         int l;
197         
198         l=ip->len/4;
199         for (r=0; r<l; r++)
200                 if (ip->u.addr32[r]!=0)
201                         return 0;
202         return 1;
203 }
204
205
206
207 /* returns 1 if ip & net.mask == net.ip ; 0 otherwise & -1 on error 
208         [ diff. address families ]) */
209 inline static int matchnet(struct ip_addr* ip, struct net* net)
210 {
211         unsigned int r;
212         int ret;
213         
214         ret=-1;
215         if (ip->af == net->ip.af){
216                 for(r=0; r<ip->len/4; r++){ /* ipv4 & ipv6 addresses are
217                                                                            all multiple of 4*/
218                         if ((ip->u.addr32[r]&net->mask.u.addr32[r])!=
219                                                                                                                  net->ip.u.addr32[r]){
220                                 return 0;
221                         }
222                 }
223                 return 1;
224         };
225         return -1;
226 }
227
228
229
230
231 /* inits an ip_addr pointer from a sockaddr structure*/
232 static inline void sockaddr2ip_addr(struct ip_addr* ip, struct sockaddr* sa)
233 {
234         switch(sa->sa_family){
235         case AF_INET:
236                         ip->af=AF_INET;
237                         ip->len=4;
238                         memcpy(ip->u.addr, &((struct sockaddr_in*)sa)->sin_addr, 4);
239                         break;
240 #ifdef USE_IPV6
241         case AF_INET6:
242                         ip->af=AF_INET6;
243                         ip->len=16;
244                         memcpy(ip->u.addr, &((struct sockaddr_in6*)sa)->sin6_addr, 16);
245                         break;
246 #endif
247         default:
248                         LOG(L_CRIT, "sockaddr2ip_addr: BUG: unknown address family %d\n",
249                                         sa->sa_family);
250         }
251 }
252
253
254
255 /* compare 2 ip_addrs (both args are pointers)*/
256 #define ip_addr_cmp(ip1, ip2) \
257         (((ip1)->af==(ip2)->af)&& \
258                 (memcmp((ip1)->u.addr, (ip2)->u.addr, (ip1)->len)==0))
259
260
261
262 /* compare 2 sockaddr_unions */
263 static inline int su_cmp(union sockaddr_union* s1, union sockaddr_union* s2)
264 {
265         if (s1->s.sa_family!=s2->s.sa_family) return 0;
266         switch(s1->s.sa_family){
267                 case AF_INET:
268                         return (s1->sin.sin_port==s2->sin.sin_port)&&
269                                         (memcmp(&s1->sin.sin_addr, &s2->sin.sin_addr, 4)==0);
270 #ifdef USE_IPV6
271                 case AF_INET6:
272                         return (s1->sin6.sin6_port==s2->sin6.sin6_port)&&
273                                         (memcmp(&s1->sin6.sin6_addr, &s2->sin6.sin6_addr, 16)==0);
274 #endif
275                 default:
276                         LOG(L_CRIT,"su_cmp: BUG: unknown address family %d\n",
277                                                 s1->s.sa_family);
278                         return 0;
279         }
280 }
281
282
283
284 /* gets the port number (host byte order) */
285 static inline unsigned short su_getport(union sockaddr_union* su)
286 {
287         switch(su->s.sa_family){
288                 case AF_INET:
289                         return ntohs(su->sin.sin_port);
290 #ifdef USE_IPV6
291                 case AF_INET6:
292                         return ntohs(su->sin6.sin6_port);
293 #endif
294                 default:
295                         LOG(L_CRIT,"su_get_port: BUG: unknown address family %d\n",
296                                                 su->s.sa_family);
297                         return 0;
298         }
299 }
300
301
302
303 /* sets the port number (host byte order) */
304 static inline void su_setport(union sockaddr_union* su, unsigned short port)
305 {
306         switch(su->s.sa_family){
307                 case AF_INET:
308                         su->sin.sin_port=htons(port);
309                         break;
310 #ifdef USE_IPV6
311                 case AF_INET6:
312                          su->sin6.sin6_port=htons(port);
313                          break;
314 #endif
315                 default:
316                         LOG(L_CRIT,"su_set_port: BUG: unknown address family %d\n",
317                                                 su->s.sa_family);
318         }
319 }
320
321
322
323 /* inits an ip_addr pointer from a sockaddr_union ip address */
324 static inline void su2ip_addr(struct ip_addr* ip, union sockaddr_union* su)
325 {
326         switch(su->s.sa_family){
327         case AF_INET: 
328                                         ip->af=AF_INET;
329                                         ip->len=4;
330                                         memcpy(ip->u.addr, &su->sin.sin_addr, 4);
331                                         break;
332 #ifdef USE_IPV6
333         case AF_INET6:
334                                         ip->af=AF_INET6;
335                                         ip->len=16;
336                                         memcpy(ip->u.addr, &su->sin6.sin6_addr, 16);
337                                         break;
338 #endif
339         default:
340                                         LOG(L_CRIT,"su2ip_addr: BUG: unknown address family %d\n",
341                                                         su->s.sa_family);
342         }
343 }
344
345
346 /* ip_addr2su -> the same as init_su*/
347 #define ip_addr2su init_su
348
349 /* inits a struct sockaddr_union from a struct ip_addr and a port no 
350  * returns 0 if ok, -1 on error (unknown address family)
351  * the port number is in host byte order */
352 static inline int init_su( union sockaddr_union* su,
353                                                         struct ip_addr* ip,
354                                                         unsigned short   port ) 
355 {
356         memset(su, 0, sizeof(union sockaddr_union));/*needed on freebsd*/
357         su->s.sa_family=ip->af;
358         switch(ip->af){
359 #ifdef USE_IPV6
360         case    AF_INET6:
361                 memcpy(&su->sin6.sin6_addr, ip->u.addr, ip->len); 
362                 #ifdef HAVE_SOCKADDR_SA_LEN
363                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
364                 #endif
365                 su->sin6.sin6_port=htons(port);
366                 break;
367 #endif
368         case AF_INET:
369                 memcpy(&su->sin.sin_addr, ip->u.addr, ip->len);
370                 #ifdef HAVE_SOCKADDR_SA_LEN
371                         su->sin.sin_len=sizeof(struct sockaddr_in);
372                 #endif
373                 su->sin.sin_port=htons(port);
374                 break;
375         default:
376                 LOG(L_CRIT, "init_ss: BUG: unknown address family %d\n", ip->af);
377                 return -1;
378         }
379         return 0;
380 }
381
382
383
384 /* inits a struct sockaddr_union from a struct hostent, an address index in
385  * the hostent structure and a port no. (host byte order)
386  * WARNING: no index overflow  checks!
387  * returns 0 if ok, -1 on error (unknown address family) */
388 static inline int hostent2su( union sockaddr_union* su,
389                                                                 struct hostent* he,
390                                                                 unsigned int idx,
391                                                                 unsigned short   port ) 
392 {
393         memset(su, 0, sizeof(union sockaddr_union)); /*needed on freebsd*/
394         su->s.sa_family=he->h_addrtype;
395         switch(he->h_addrtype){
396 #ifdef USE_IPV6
397         case    AF_INET6:
398                 memcpy(&su->sin6.sin6_addr, he->h_addr_list[idx], he->h_length);
399                 #ifdef HAVE_SOCKADDR_SA_LEN
400                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
401                 #endif
402                 su->sin6.sin6_port=htons(port);
403                 break;
404 #endif
405         case AF_INET:
406                 memcpy(&su->sin.sin_addr, he->h_addr_list[idx], he->h_length);
407                 #ifdef HAVE_SOCKADDR_SA_LEN
408                         su->sin.sin_len=sizeof(struct sockaddr_in);
409                 #endif
410                 su->sin.sin_port=htons(port);
411                 break;
412         default:
413                 LOG(L_CRIT, "hostent2su: BUG: unknown address family %d\n", 
414                                 he->h_addrtype);
415                 return -1;
416         }
417         return 0;
418 }
419
420 /* maximum size of a str returned by ip_addr2a (including \0) */
421 #define IP_ADDR_MAX_STR_SIZE 40 /* 1234:5678:9012:3456:7890:1234:5678:9012\0 */
422 /* fast ip_addr -> string converter;
423  * it uses an internal buffer
424  */
425 static inline char* ip_addr2a(struct ip_addr* ip)
426 {
427
428         static char buff[IP_ADDR_MAX_STR_SIZE];
429         int offset;
430         register unsigned char a,b,c;
431 #ifdef USE_IPV6
432         register unsigned char d;
433         register unsigned short hex4;
434 #endif
435         int r;
436         #define HEXDIG(x) (((x)>=10)?(x)-10+'A':(x)+'0')
437         
438         
439         offset=0;
440         switch(ip->af){
441         #ifdef USE_IPV6
442                 case AF_INET6:
443                         for(r=0;r<7;r++){
444                                 hex4=ntohs(ip->u.addr16[r]);
445                                 a=hex4>>12;
446                                 b=(hex4>>8)&0xf;
447                                 c=(hex4>>4)&0xf;
448                                 d=hex4&0xf;
449                                 if (a){
450                                         buff[offset]=HEXDIG(a);
451                                         buff[offset+1]=HEXDIG(b);
452                                         buff[offset+2]=HEXDIG(c);
453                                         buff[offset+3]=HEXDIG(d);
454                                         buff[offset+4]=':';
455                                         offset+=5;
456                                 }else if(b){
457                                         buff[offset]=HEXDIG(b);
458                                         buff[offset+1]=HEXDIG(c);
459                                         buff[offset+2]=HEXDIG(d);
460                                         buff[offset+3]=':';
461                                         offset+=4;
462                                 }else if(c){
463                                         buff[offset]=HEXDIG(c);
464                                         buff[offset+1]=HEXDIG(d);
465                                         buff[offset+2]=':';
466                                         offset+=3;
467                                 }else{
468                                         buff[offset]=HEXDIG(d);
469                                         buff[offset+1]=':';
470                                         offset+=2;
471                                 }
472                         }
473                         /* last int16*/
474                         hex4=ntohs(ip->u.addr16[r]);
475                         a=hex4>>12;
476                         b=(hex4>>8)&0xf;
477                         c=(hex4>>4)&0xf;
478                         d=hex4&0xf;
479                         if (a){
480                                 buff[offset]=HEXDIG(a);
481                                 buff[offset+1]=HEXDIG(b);
482                                 buff[offset+2]=HEXDIG(c);
483                                 buff[offset+3]=HEXDIG(d);
484                                 buff[offset+4]=0;
485                         }else if(b){
486                                 buff[offset]=HEXDIG(b);
487                                 buff[offset+1]=HEXDIG(c);
488                                 buff[offset+2]=HEXDIG(d);
489                                 buff[offset+3]=0;
490                         }else if(c){
491                                 buff[offset]=HEXDIG(c);
492                                 buff[offset+1]=HEXDIG(d);
493                                 buff[offset+2]=0;
494                         }else{
495                                 buff[offset]=HEXDIG(d);
496                                 buff[offset+1]=0;
497                         }
498                         break;
499         #endif
500                 case AF_INET:
501                         for(r=0;r<3;r++){
502                                 a=ip->u.addr[r]/100;
503                                 c=ip->u.addr[r]%10;
504                                 b=ip->u.addr[r]%100/10;
505                                 if (a){
506                                         buff[offset]=a+'0';
507                                         buff[offset+1]=b+'0';
508                                         buff[offset+2]=c+'0';
509                                         buff[offset+3]='.';
510                                         offset+=4;
511                                 }else if (b){
512                                         buff[offset]=b+'0';
513                                         buff[offset+1]=c+'0';
514                                         buff[offset+2]='.';
515                                         offset+=3;
516                                 }else{
517                                         buff[offset]=c+'0';
518                                         buff[offset+1]='.';
519                                         offset+=2;
520                                 }
521                         }
522                         /* last number */
523                         a=ip->u.addr[r]/100;
524                         c=ip->u.addr[r]%10;
525                         b=ip->u.addr[r]%100/10;
526                         if (a){
527                                 buff[offset]=a+'0';
528                                 buff[offset+1]=b+'0';
529                                 buff[offset+2]=c+'0';
530                                 buff[offset+3]=0;
531                         }else if (b){
532                                 buff[offset]=b+'0';
533                                 buff[offset+1]=c+'0';
534                                 buff[offset+2]=0;
535                         }else{
536                                 buff[offset]=c+'0';
537                                 buff[offset+1]=0;
538                         }
539                         break;
540                 
541                 default:
542                         LOG(L_CRIT, "BUG: ip_addr2a: unknown address family %d\n",
543                                         ip->af);
544                         return 0;
545         }
546         
547         return buff;
548 }
549
550
551
552 /* converts an ip_addr structure to a hostent, returns pointer to internal
553  * statical structure */
554 static inline struct hostent* ip_addr2he(str* name, struct ip_addr* ip)
555 {
556         static struct hostent he;
557         static char hostname[256];
558         static char* p_aliases[1];
559         static char* p_addr[2];
560         static char address[16];
561         
562         p_aliases[0]=0; /* no aliases*/
563         p_addr[1]=0; /* only one address*/
564         p_addr[0]=address;
565         strncpy(hostname, name->s, (name->len<256)?(name->len)+1:256);
566         if (ip->len>16) return 0;
567         memcpy(address, ip->u.addr, ip->len);
568         
569         he.h_addrtype=ip->af;
570         he.h_length=ip->len;
571         he.h_addr_list=p_addr;
572         he.h_aliases=p_aliases;
573         he.h_name=hostname;
574         return &he;
575 }
576
577
578
579 /* init a dest_info structure */
580 #define init_dest_info(dst) \
581         do{ \
582                 memset((dst), 0, sizeof(struct dest_info)); \
583         } while(0) 
584
585
586
587 /* init a dest_info structure from a recv_info structure */
588 inline static void init_dst_from_rcv(struct dest_info* dst,
589                                                                         struct receive_info* rcv)
590 {
591                 dst->send_sock=rcv->bind_address;
592                 dst->to=rcv->src_su;
593                 dst->id=rcv->proto_reserved1;
594                 dst->proto=rcv->proto;
595 #ifdef USE_COMP
596                 dst->comp=rcv->comp;
597 #endif
598 }
599
600
601 #endif