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