pkg/kamailio/fedora/16: Updated rel in .spec to dev2
[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  *  2007-06-26  added ip_addr_mk_any() (andrei)
36  *  2008-05-21  added su2a(), ip_addr2sbuf(), ip4tosbuf(), ip62sbuf() (andrei)
37  *  2009-09-14  added send flags support to dest_info (andrei)
38  */
39
40 #ifndef ip_addr_h
41 #define ip_addr_h
42
43 #include <string.h>
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <netinet/in.h>
47 #include <netdb.h>
48 #include "str.h"
49 #include "compiler_opt.h"
50 #include "ut.h"
51
52
53 #include "dprint.h"
54
55 enum sip_protos { PROTO_NONE, PROTO_UDP, PROTO_TCP, PROTO_TLS, PROTO_SCTP, PROTO_WS, PROTO_WSS, PROTO_OTHER };
56 #define PROTO_LAST PROTO_OTHER
57
58 #ifdef USE_COMP
59 enum comp_methods { COMP_NONE, COMP_SIGCOMP, COMP_SERGZ };
60 #endif
61
62 struct ip_addr{
63         unsigned int af; /* address family: AF_INET6 or AF_INET */
64         unsigned int len;    /* address len, 16 or 4 */
65         
66         /* 64 bits aligned address */
67         union {
68                 unsigned long  addrl[16/sizeof(long)]; /* long format*/
69                 unsigned int   addr32[4];
70                 unsigned short addr16[8];
71                 unsigned char  addr[16];
72         }u;
73 };
74
75 typedef struct ip_addr ip_addr_t;
76
77 struct net{
78         struct ip_addr ip;
79         struct ip_addr mask;
80 };
81
82 union sockaddr_union{
83                 struct sockaddr     s;
84                 struct sockaddr_in  sin;
85         #ifdef USE_IPV6
86                 struct sockaddr_in6 sin6;
87         #endif
88 };
89
90
91
92 enum si_flags { SI_NONE=0, SI_IS_IP=1, SI_IS_LO=2, SI_IS_MCAST=4,
93                                  SI_IS_ANY=8, SI_IS_MHOMED=16 };
94
95 struct addr_info{
96         str name; /* name - eg.: foo.bar or 10.0.0.1 */
97         struct ip_addr address; /*ip address */
98         str address_str;        /*ip address converted to string -- optimization*/
99         enum si_flags flags; /* SI_IS_IP | SI_IS_LO | SI_IS_MCAST */
100         union sockaddr_union su;
101         struct addr_info* next;
102         struct addr_info* prev;
103 };
104
105 struct advertise_info {
106         str name; /* name - eg.: foo.bar or 10.0.0.1 */
107         unsigned short port_no;  /* port number */
108         str port_no_str; /* port number converted to string -- optimization*/
109         str address_str;        /*ip address converted to string -- optimization*/
110         struct ip_addr address; /* ip address */
111         str sock_str; /* Socket proto, ip, and port as string */
112 };
113
114 struct socket_info{
115         int socket;
116         str name; /* name - eg.: foo.bar or 10.0.0.1 */
117         struct ip_addr address; /* ip address */
118         str address_str;        /*ip address converted to string -- optimization*/
119         str port_no_str; /* port number converted to string -- optimization*/
120         enum si_flags flags; /* SI_IS_IP | SI_IS_LO | SI_IS_MCAST */
121         union sockaddr_union su; 
122         struct socket_info* next;
123         struct socket_info* prev;
124         unsigned short port_no;  /* port number */
125         char proto; /* tcp or udp*/
126         str sock_str; /* Socket proto, ip, and port as string */
127         struct addr_info* addr_info_lst; /* extra addresses (e.g. SCTP mh) */
128         int workers; /* number of worker processes for this socket */
129         int workers_tcpidx; /* index of workers in tcp children array */
130         struct advertise_info useinfo; /* details to be used in SIP msg */
131 };
132
133
134 struct receive_info{
135         struct ip_addr src_ip;
136         struct ip_addr dst_ip;
137         unsigned short src_port; /* host byte order */
138         unsigned short dst_port; /* host byte order */
139         int proto_reserved1; /* tcp stores the connection id here */
140         int proto_reserved2;
141         union sockaddr_union src_su; /* useful for replies*/
142         struct socket_info* bind_address; /* sock_info structure on which 
143                                                                           the msg was received*/
144         char proto;
145 #ifdef USE_COMP
146         short comp; /* compression */
147 #endif
148         /* no need for dst_su yet */
149 };
150
151
152 /* send flags */
153 #define SND_F_FORCE_CON_REUSE   1 /* reuse an existing connection or fail */
154 #define SND_F_CON_CLOSE                 2 /* close the connection after sending */
155 #define SND_F_FORCE_SOCKET              4 /* send socket in dst is forced */
156
157 struct snd_flags {
158         unsigned char f;          /* snd flags */
159         unsigned char blst_imask; /* blacklist ignore mask */
160 };
161
162
163 typedef struct snd_flags  snd_flags_t;
164
165 #define SND_FLAGS_INIT(sflags) \
166         do{ \
167                 (sflags)->f=0; \
168                 (sflags)->blst_imask=0; \
169         }while(0)
170
171 #define SND_FLAGS_OR(dst, src1, src2) \
172         do{ \
173                 (dst)->f = (src1)->f | (src2)->f; \
174                 (dst)->blst_imask = (src1)->blst_imask | (src2)->blst_imask; \
175         }while(0)
176
177 #define SND_FLAGS_AND(dst, src1, src2) \
178         do{ \
179                 (dst)->f = (src1)->f & (src2)->f; \
180                 (dst)->blst_imask = (src1)->blst_imask & (src2)->blst_imask; \
181         }while(0)
182
183 struct dest_info{
184         struct socket_info* send_sock;
185         union sockaddr_union to;
186         int id; /* tcp stores the connection id here */ 
187         char proto;
188         snd_flags_t send_flags;
189 #ifdef USE_COMP
190         short comp;
191 #endif
192 };
193
194
195 /* list of names for multi-homed sockets that need to bind on
196  * multiple addresses in the same time (sctp ) */
197 struct name_lst{
198         char* name;
199         struct name_lst* next;
200         int flags;
201 };
202
203
204 struct socket_id{
205         struct name_lst* addr_lst; /* address list, the first one must
206                                                                   be present and is the main one
207                                                                   (in case of multihoming sctp)*/
208         int flags;
209         int proto;
210         int port;
211         struct socket_id* next;
212 };
213
214
215
216 /* len of the sockaddr */
217 #ifdef HAVE_SOCKADDR_SA_LEN
218 #define sockaddru_len(su)       ((su).s.sa_len)
219 #else
220 #ifdef USE_IPV6
221 #define sockaddru_len(su)       \
222                         (((su).s.sa_family==AF_INET6)?sizeof(struct sockaddr_in6):\
223                                         sizeof(struct sockaddr_in))
224 #else
225 #define sockaddru_len(su)       sizeof(struct sockaddr_in)
226 #endif /*USE_IPV6*/
227 #endif /* HAVE_SOCKADDR_SA_LEN*/
228         
229 /* inits an ip_addr with the addr. info from a hostent structure
230  * ip = struct ip_addr*
231  * he= struct hostent*
232  */
233 #define hostent2ip_addr(ip, he, addr_no) \
234         do{ \
235                 (ip)->af=(he)->h_addrtype; \
236                 (ip)->len=(he)->h_length;  \
237                 memcpy((ip)->u.addr, (he)->h_addr_list[(addr_no)], (ip)->len); \
238         }while(0)
239         
240
241
242
243 /* gets the protocol family corresponding to a specific address family
244  * ( PF_INET - AF_INET, PF_INET6 - AF_INET6, af for others)
245  */
246 #ifdef USE_IPV6
247 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:((af)==AF_INET6)?PF_INET6:(af))
248 #else
249 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:(af))
250 #endif
251
252
253
254
255 struct net* mk_new_net(struct ip_addr* ip, struct ip_addr* mask);
256 struct net* mk_new_net_bitlen(struct ip_addr* ip, unsigned int bitlen);
257 int mk_net(struct net* n, struct ip_addr* ip, struct ip_addr* mask);
258 int mk_net_bitlen(struct net* n, struct ip_addr* ip, unsigned int bitlen);
259 int mk_net_str(struct net* dst, str* s);
260
261 void print_ip(char* prefix, struct ip_addr* ip, char* suffix);
262 void stdout_print_ip(struct ip_addr* ip);
263 void print_net(struct net* net);
264
265 char* get_proto_name(unsigned int proto);
266 #define proto2a get_proto_name
267
268
269
270 #ifdef USE_MCAST
271 /* Returns 1 if the given address is a multicast address */
272 int is_mcast(struct ip_addr* ip);
273 #endif /* USE_MCAST */
274
275 /* returns 1 if the given ip address is INADDR_ANY or IN6ADDR_ANY,
276  * 0 otherwise */
277 inline static int ip_addr_any(struct ip_addr* ip)
278 {
279         int r;
280         int l;
281         
282         l=ip->len/4;
283         for (r=0; r<l; r++)
284                 if (ip->u.addr32[r]!=0)
285                         return 0;
286         return 1;
287 }
288
289
290
291 /* returns 1 if the given ip address is a loopback address
292  * 0 otherwise */
293 inline static int ip_addr_loopback(struct ip_addr* ip)
294 {
295         if (ip->af==AF_INET)
296                 return ip->u.addr32[0]==htonl(INADDR_LOOPBACK);
297 #ifdef USE_IPV6
298         else if (ip->af==AF_INET6)
299                 return IN6_IS_ADDR_LOOPBACK((struct in6_addr*)ip->u.addr32);
300 #endif /* USE_IPV6 */
301         return 0;
302 }
303
304
305
306 /* creates an ANY ip_addr (filled with 0, af and len properly set) */
307 inline static void ip_addr_mk_any(int af, struct ip_addr* ip)
308 {
309         ip->af=af;
310         if (likely(af==AF_INET)){
311                 ip->len=4;
312                 ip->u.addr32[0]=0;
313         }
314 #ifdef USE_IPV6
315         else{
316                 ip->len=16;
317 #if (defined (ULONG_MAX) && ULONG_MAX > 4294967295) || defined LP64
318                 /* long is 64 bits */
319                 ip->u.addrl[0]=0;
320                 ip->u.addrl[1]=0;
321 #else
322                 ip->u.addr32[0]=0;
323                 ip->u.addr32[1]=0;
324                 ip->u.addr32[2]=0;
325                 ip->u.addr32[3]=0;
326 #endif /* ULONG_MAX */
327         }
328 #endif
329 }
330
331 /* returns 1 if ip & net.mask == net.ip ; 0 otherwise & -1 on error 
332         [ diff. address families ]) */
333 inline static int matchnet(struct ip_addr* ip, struct net* net)
334 {
335         unsigned int r;
336
337         if (ip->af == net->ip.af){
338                 for(r=0; r<ip->len/4; r++){ /* ipv4 & ipv6 addresses are
339                                                                            all multiple of 4*/
340                         if ((ip->u.addr32[r]&net->mask.u.addr32[r])!=
341                                                                                                                  net->ip.u.addr32[r]){
342                                 return 0;
343                         }
344                 }
345                 return 1;
346         };
347         return -1;
348 }
349
350
351
352
353 /* inits an ip_addr pointer from a sockaddr structure*/
354 static inline void sockaddr2ip_addr(struct ip_addr* ip, struct sockaddr* sa)
355 {
356         switch(sa->sa_family){
357         case AF_INET:
358                         ip->af=AF_INET;
359                         ip->len=4;
360                         memcpy(ip->u.addr, &((struct sockaddr_in*)sa)->sin_addr, 4);
361                         break;
362 #ifdef USE_IPV6
363         case AF_INET6:
364                         ip->af=AF_INET6;
365                         ip->len=16;
366                         memcpy(ip->u.addr, &((struct sockaddr_in6*)sa)->sin6_addr, 16);
367                         break;
368 #endif
369         default:
370                         LOG(L_CRIT, "sockaddr2ip_addr: BUG: unknown address family %d\n",
371                                         sa->sa_family);
372         }
373 }
374
375
376
377 /* compare 2 ip_addrs (both args are pointers)*/
378 #define ip_addr_cmp(ip1, ip2) \
379         (((ip1)->af==(ip2)->af)&& \
380                 (memcmp((ip1)->u.addr, (ip2)->u.addr, (ip1)->len)==0))
381
382
383
384 /* compare 2 sockaddr_unions */
385 static inline int su_cmp(const union sockaddr_union* s1,
386                                                  const union sockaddr_union* s2)
387 {
388         if (s1->s.sa_family!=s2->s.sa_family) return 0;
389         switch(s1->s.sa_family){
390                 case AF_INET:
391                         return (s1->sin.sin_port==s2->sin.sin_port)&&
392                                         (memcmp(&s1->sin.sin_addr, &s2->sin.sin_addr, 4)==0);
393 #ifdef USE_IPV6
394                 case AF_INET6:
395                         return (s1->sin6.sin6_port==s2->sin6.sin6_port)&&
396                                         (memcmp(&s1->sin6.sin6_addr, &s2->sin6.sin6_addr, 16)==0);
397 #endif
398                 default:
399                         LOG(L_CRIT,"su_cmp: BUG: unknown address family %d\n",
400                                                 s1->s.sa_family);
401                         return 0;
402         }
403 }
404
405
406
407 /* gets the port number (host byte order) */
408 static inline unsigned short su_getport(const union sockaddr_union* su)
409 {
410         switch(su->s.sa_family){
411                 case AF_INET:
412                         return ntohs(su->sin.sin_port);
413 #ifdef USE_IPV6
414                 case AF_INET6:
415                         return ntohs(su->sin6.sin6_port);
416 #endif
417                 default:
418                         LOG(L_CRIT,"su_get_port: BUG: unknown address family %d\n",
419                                                 su->s.sa_family);
420                         return 0;
421         }
422 }
423
424
425
426 /* sets the port number (host byte order) */
427 static inline void su_setport(union sockaddr_union* su, unsigned short port)
428 {
429         switch(su->s.sa_family){
430                 case AF_INET:
431                         su->sin.sin_port=htons(port);
432                         break;
433 #ifdef USE_IPV6
434                 case AF_INET6:
435                          su->sin6.sin6_port=htons(port);
436                          break;
437 #endif
438                 default:
439                         LOG(L_CRIT,"su_set_port: BUG: unknown address family %d\n",
440                                                 su->s.sa_family);
441         }
442 }
443
444
445
446 /* inits an ip_addr pointer from a sockaddr_union ip address */
447 static inline void su2ip_addr(struct ip_addr* ip, union sockaddr_union* su)
448 {
449         switch(su->s.sa_family){
450         case AF_INET: 
451                                         ip->af=AF_INET;
452                                         ip->len=4;
453                                         memcpy(ip->u.addr, &su->sin.sin_addr, 4);
454                                         break;
455 #ifdef USE_IPV6
456         case AF_INET6:
457                                         ip->af=AF_INET6;
458                                         ip->len=16;
459                                         memcpy(ip->u.addr, &su->sin6.sin6_addr, 16);
460                                         break;
461 #endif
462         default:
463                                         LOG(L_CRIT,"su2ip_addr: BUG: unknown address family %d\n",
464                                                         su->s.sa_family);
465         }
466 }
467
468
469 /* ip_addr2su -> the same as init_su*/
470 #define ip_addr2su init_su
471
472 /* inits a struct sockaddr_union from a struct ip_addr and a port no 
473  * returns 0 if ok, -1 on error (unknown address family)
474  * the port number is in host byte order */
475 static inline int init_su( union sockaddr_union* su,
476                                                         struct ip_addr* ip,
477                                                         unsigned short   port ) 
478 {
479         memset(su, 0, sizeof(union sockaddr_union));/*needed on freebsd*/
480         su->s.sa_family=ip->af;
481         switch(ip->af){
482 #ifdef USE_IPV6
483         case    AF_INET6:
484                 memcpy(&su->sin6.sin6_addr, ip->u.addr, ip->len); 
485                 #ifdef HAVE_SOCKADDR_SA_LEN
486                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
487                 #endif
488                 su->sin6.sin6_port=htons(port);
489                 break;
490 #endif
491         case AF_INET:
492                 memcpy(&su->sin.sin_addr, ip->u.addr, ip->len);
493                 #ifdef HAVE_SOCKADDR_SA_LEN
494                         su->sin.sin_len=sizeof(struct sockaddr_in);
495                 #endif
496                 su->sin.sin_port=htons(port);
497                 break;
498         default:
499                 LOG(L_CRIT, "init_ss: BUG: unknown address family %d\n", ip->af);
500                 return -1;
501         }
502         return 0;
503 }
504
505
506
507 /* inits a struct sockaddr_union from a struct hostent, an address index in
508  * the hostent structure and a port no. (host byte order)
509  * WARNING: no index overflow  checks!
510  * returns 0 if ok, -1 on error (unknown address family) */
511 static inline int hostent2su( union sockaddr_union* su,
512                                                                 struct hostent* he,
513                                                                 unsigned int idx,
514                                                                 unsigned short   port ) 
515 {
516         memset(su, 0, sizeof(union sockaddr_union)); /*needed on freebsd*/
517         su->s.sa_family=he->h_addrtype;
518         switch(he->h_addrtype){
519 #ifdef USE_IPV6
520         case    AF_INET6:
521                 memcpy(&su->sin6.sin6_addr, he->h_addr_list[idx], he->h_length);
522                 #ifdef HAVE_SOCKADDR_SA_LEN
523                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
524                 #endif
525                 su->sin6.sin6_port=htons(port);
526                 break;
527 #endif
528         case AF_INET:
529                 memcpy(&su->sin.sin_addr, he->h_addr_list[idx], he->h_length);
530                 #ifdef HAVE_SOCKADDR_SA_LEN
531                         su->sin.sin_len=sizeof(struct sockaddr_in);
532                 #endif
533                 su->sin.sin_port=htons(port);
534                 break;
535         default:
536                 LOG(L_CRIT, "hostent2su: BUG: unknown address family %d\n", 
537                                 he->h_addrtype);
538                 return -1;
539         }
540         return 0;
541 }
542
543
544
545 /* maximum size of a str returned by ip_addr2str */
546 #define IP6_MAX_STR_SIZE 39 /*1234:5678:9012:3456:7890:1234:5678:9012*/
547 #define IP4_MAX_STR_SIZE 15 /*123.456.789.012*/
548
549 #ifdef USE_IPV6
550 /* converts a raw ipv6 addr (16 bytes) to ascii */
551 static inline int ip6tosbuf(unsigned char* ip6, char* buff, int len)
552 {
553         int offset;
554         register unsigned char a,b,c;
555         register unsigned char d;
556         register unsigned short hex4;
557         int r;
558         #define HEXDIG(x) (((x)>=10)?(x)-10+'A':(x)+'0')
559         
560         
561         offset=0;
562         if (unlikely(len<IP6_MAX_STR_SIZE))
563                 return 0;
564         for(r=0;r<7;r++){
565                 hex4=((unsigned char)ip6[r*2]<<8)+(unsigned char)ip6[r*2+1];
566                 a=hex4>>12;
567                 b=(hex4>>8)&0xf;
568                 c=(hex4>>4)&0xf;
569                 d=hex4&0xf;
570                 if (a){
571                         buff[offset]=HEXDIG(a);
572                         buff[offset+1]=HEXDIG(b);
573                         buff[offset+2]=HEXDIG(c);
574                         buff[offset+3]=HEXDIG(d);
575                         buff[offset+4]=':';
576                         offset+=5;
577                 }else if(b){
578                         buff[offset]=HEXDIG(b);
579                         buff[offset+1]=HEXDIG(c);
580                         buff[offset+2]=HEXDIG(d);
581                         buff[offset+3]=':';
582                         offset+=4;
583                 }else if(c){
584                         buff[offset]=HEXDIG(c);
585                         buff[offset+1]=HEXDIG(d);
586                         buff[offset+2]=':';
587                         offset+=3;
588                 }else{
589                         buff[offset]=HEXDIG(d);
590                         buff[offset+1]=':';
591                         offset+=2;
592                 }
593         }
594         /* last int16*/
595         hex4=((unsigned char)ip6[r*2]<<8)+(unsigned char)ip6[r*2+1];
596         a=hex4>>12;
597         b=(hex4>>8)&0xf;
598         c=(hex4>>4)&0xf;
599         d=hex4&0xf;
600         if (a){
601                 buff[offset]=HEXDIG(a);
602                 buff[offset+1]=HEXDIG(b);
603                 buff[offset+2]=HEXDIG(c);
604                 buff[offset+3]=HEXDIG(d);
605                 offset+=4;
606         }else if(b){
607                 buff[offset]=HEXDIG(b);
608                 buff[offset+1]=HEXDIG(c);
609                 buff[offset+2]=HEXDIG(d);
610                 offset+=3;
611         }else if(c){
612                 buff[offset]=HEXDIG(c);
613                 buff[offset+1]=HEXDIG(d);
614                 offset+=2;
615         }else{
616                 buff[offset]=HEXDIG(d);
617                 offset+=1;
618         }
619         
620         return offset;
621 }
622 #endif /* USE_IPV6 */
623
624
625
626 /* converts a raw ipv4 addr (4 bytes) to ascii */
627 static inline int ip4tosbuf(unsigned char* ip4, char* buff, int len)
628 {
629         int offset;
630         register unsigned char a,b,c;
631         int r;
632         
633         
634         offset=0;
635         if (unlikely(len<IP4_MAX_STR_SIZE))
636                 return 0;
637         for(r=0;r<3;r++){
638                 a=(unsigned char)ip4[r]/100;
639                 c=(unsigned char)ip4[r]%10;
640                 b=(unsigned char)ip4[r]%100/10;
641                 if (a){
642                         buff[offset]=a+'0';
643                         buff[offset+1]=b+'0';
644                         buff[offset+2]=c+'0';
645                         buff[offset+3]='.';
646                         offset+=4;
647                 }else if (b){
648                         buff[offset]=b+'0';
649                         buff[offset+1]=c+'0';
650                         buff[offset+2]='.';
651                         offset+=3;
652                 }else{
653                         buff[offset]=c+'0';
654                         buff[offset+1]='.';
655                         offset+=2;
656                 }
657         }
658         /* last number */
659         a=(unsigned char)ip4[r]/100;
660         c=(unsigned char)ip4[r]%10;
661         b=(unsigned char)ip4[r]%100/10;
662         if (a){
663                 buff[offset]=a+'0';
664                 buff[offset+1]=b+'0';
665                 buff[offset+2]=c+'0';
666                 offset+=3;
667         }else if (b){
668                 buff[offset]=b+'0';
669                 buff[offset+1]=c+'0';
670                 offset+=2;
671         }else{
672                 buff[offset]=c+'0';
673                 offset+=1;
674         }
675         
676         return offset;
677 }
678
679
680
681 /* fast ip_addr -> string converter;
682  * returns number of bytes written in buf on success, <=0 on error
683  * The buffer must have enough space to hold the maximum size ip address
684  *  of the corresponding address (see IP[46] above) or else the function
685  *  will return error (no detailed might fit checks are made, for example
686  *   if len==7 the function will fail even for 1.2.3.4).
687  */
688 static inline int ip_addr2sbuf(struct ip_addr* ip, char* buff, int len)
689 {
690         switch(ip->af){
691         #ifdef USE_IPV6
692                 case AF_INET6:
693                         return ip6tosbuf(ip->u.addr, buff, len);
694                         break;
695         #endif /* USE_IPV6 */
696                 case AF_INET:
697                         return ip4tosbuf(ip->u.addr, buff, len);
698                         break;
699                 default:
700                         LOG(L_CRIT, "BUG: ip_addr2sbuf: unknown address family %d\n",
701                                         ip->af);
702                         return 0;
703         }
704         return 0;
705 }
706
707
708
709 /* maximum size of a str returned by ip_addr2a (including \0) */
710 #define IP_ADDR_MAX_STR_SIZE (IP6_MAX_STR_SIZE+1) /* ip62ascii +  \0*/
711 /* fast ip_addr -> string converter;
712  * it uses an internal buffer
713  */
714 static inline char* ip_addr2a(struct ip_addr* ip)
715 {
716
717         static char buff[IP_ADDR_MAX_STR_SIZE];
718         int len;
719         
720         
721         len=ip_addr2sbuf(ip, buff, sizeof(buff)-1);
722         buff[len]=0;
723
724         return buff;
725 }
726
727
728
729 #define SU2A_MAX_STR_SIZE  (IP6_MAX_STR_SIZE + 2 /* [] */+\
730                                                                 1 /* : */ + USHORT2SBUF_MAX_LEN + 1 /* \0 */)
731 /* returns an asciiz string containing the ip and the port
732  *  (<ip_addr>:port or [<ipv6_addr>]:port)
733  */
734 static inline char* su2a(union sockaddr_union* su, int su_len)
735 {
736         static char buf[SU2A_MAX_STR_SIZE];
737         int offs;
738
739 #ifdef USE_IPV6
740         if (unlikely(su->s.sa_family==AF_INET6)){
741                 if (unlikely(su_len<sizeof(su->sin6)))
742                         return "<addr. error>";
743                 buf[0]='[';
744                 offs=1+ip6tosbuf((unsigned char*)su->sin6.sin6_addr.s6_addr, &buf[1],
745                                                         sizeof(buf)-4);
746                 buf[offs]=']';
747                 offs++;
748         }else
749 #endif /* USE_IPV6*/
750         if (unlikely(su_len<sizeof(su->sin)))
751                 return "<addr. error>";
752         else
753                 offs=ip4tosbuf((unsigned char*)&su->sin.sin_addr, buf, sizeof(buf)-2);
754         buf[offs]=':';
755         offs+=1+ushort2sbuf(su_getport(su), &buf[offs+1], sizeof(buf)-(offs+1)-1);
756         buf[offs]=0;
757         return buf;
758 }
759
760 #define SUIP2A_MAX_STR_SIZE  (IP6_MAX_STR_SIZE + 2 /* [] */ + 1 /* \0 */)
761 /* returns an asciiz string containing the ip
762  *  (<ipv4_addr> or [<ipv6_addr>])
763  */
764 static inline char* suip2a(union sockaddr_union* su, int su_len)
765 {
766         static char buf[SUIP2A_MAX_STR_SIZE];
767         int offs;
768
769 #ifdef USE_IPV6
770         if (unlikely(su->s.sa_family==AF_INET6)){
771                 if (unlikely(su_len<sizeof(su->sin6)))
772                         return "<addr. error>";
773                 buf[0]='[';
774                 offs=1+ip6tosbuf((unsigned char*)su->sin6.sin6_addr.s6_addr, &buf[1],
775                                                         sizeof(buf)-4);
776                 buf[offs]=']';
777                 offs++;
778         }else
779 #endif /* USE_IPV6*/
780         if (unlikely(su_len<sizeof(su->sin)))
781                 return "<addr. error>";
782         else
783                 offs=ip4tosbuf((unsigned char*)&su->sin.sin_addr, buf, sizeof(buf)-2);
784         buf[offs]=0;
785         return buf;
786 }
787
788
789
790 /* converts an ip_addr structure to a hostent, returns pointer to internal
791  * statical structure */
792 static inline struct hostent* ip_addr2he(str* name, struct ip_addr* ip)
793 {
794         static struct hostent he;
795         static char hostname[256];
796         static char* p_aliases[1];
797         static char* p_addr[2];
798         static char address[16];
799         
800         p_aliases[0]=0; /* no aliases*/
801         p_addr[1]=0; /* only one address*/
802         p_addr[0]=address;
803         strncpy(hostname, name->s, (name->len<256)?(name->len)+1:256);
804         if (ip->len>16) return 0;
805         memcpy(address, ip->u.addr, ip->len);
806         
807         he.h_addrtype=ip->af;
808         he.h_length=ip->len;
809         he.h_addr_list=p_addr;
810         he.h_aliases=p_aliases;
811         he.h_name=hostname;
812         return &he;
813 }
814
815
816
817 /* init a dest_info structure */
818 #define init_dest_info(dst) \
819         do{ \
820                 memset((dst), 0, sizeof(struct dest_info)); \
821         } while(0) 
822
823
824
825 /* init a dest_info structure from a recv_info structure */
826 inline static void init_dst_from_rcv(struct dest_info* dst,
827                                                                         struct receive_info* rcv)
828 {
829                 dst->send_sock=rcv->bind_address;
830                 dst->to=rcv->src_su;
831                 dst->id=rcv->proto_reserved1;
832                 dst->proto=rcv->proto;
833                 dst->send_flags.f=0;
834                 dst->send_flags.blst_imask=0;
835 #ifdef USE_COMP
836                 dst->comp=rcv->comp;
837 #endif
838 }
839
840 /**
841  * match ip address with net address and bitmask
842  * - return 0 on match, -1 otherwise
843  */
844 int ip_addr_match_net(ip_addr_t *iaddr, ip_addr_t *naddr, int mask);
845
846 #endif