pkg: fix wrong package name, closes FS#148, reported from Andrew Pogrebennyk
[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 };
56 #define PROTO_LAST PROTO_SCTP
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
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 socket_info{
106         int socket;
107         str name; /* name - eg.: foo.bar or 10.0.0.1 */
108         struct ip_addr address; /* ip address */
109         str address_str;        /*ip address converted to string -- optimization*/
110         str port_no_str; /* port number converted to string -- optimization*/
111         enum si_flags flags; /* SI_IS_IP | SI_IS_LO | SI_IS_MCAST */
112         union sockaddr_union su; 
113         struct socket_info* next;
114         struct socket_info* prev;
115         unsigned short port_no;  /* port number */
116         char proto; /* tcp or udp*/
117         str sock_str; /* Socket proto, ip, and port as string */
118         struct addr_info* addr_info_lst; /* extra addresses (e.g. SCTP mh) */
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 #ifdef USE_IPV6
209 #define sockaddru_len(su)       \
210                         (((su).s.sa_family==AF_INET6)?sizeof(struct sockaddr_in6):\
211                                         sizeof(struct sockaddr_in))
212 #else
213 #define sockaddru_len(su)       sizeof(struct sockaddr_in)
214 #endif /*USE_IPV6*/
215 #endif /* HAVE_SOCKADDR_SA_LEN*/
216         
217 /* inits an ip_addr with the addr. info from a hostent structure
218  * ip = struct ip_addr*
219  * he= struct hostent*
220  */
221 #define hostent2ip_addr(ip, he, addr_no) \
222         do{ \
223                 (ip)->af=(he)->h_addrtype; \
224                 (ip)->len=(he)->h_length;  \
225                 memcpy((ip)->u.addr, (he)->h_addr_list[(addr_no)], (ip)->len); \
226         }while(0)
227         
228
229
230
231 /* gets the protocol family corresponding to a specific address family
232  * ( PF_INET - AF_INET, PF_INET6 - AF_INET6, af for others)
233  */
234 #ifdef USE_IPV6
235 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:((af)==AF_INET6)?PF_INET6:(af))
236 #else
237 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:(af))
238 #endif
239
240
241
242
243 struct net* mk_new_net(struct ip_addr* ip, struct ip_addr* mask);
244 struct net* mk_new_net_bitlen(struct ip_addr* ip, unsigned int bitlen);
245 int mk_net(struct net* n, struct ip_addr* ip, struct ip_addr* mask);
246 int mk_net_bitlen(struct net* n, struct ip_addr* ip, unsigned int bitlen);
247 int mk_net_str(struct net* dst, str* s);
248
249 void print_ip(char* prefix, struct ip_addr* ip, char* suffix);
250 void stdout_print_ip(struct ip_addr* ip);
251 void print_net(struct net* net);
252
253 char* proto2a(enum sip_protos proto);
254
255
256
257 #ifdef USE_MCAST
258 /* Returns 1 if the given address is a multicast address */
259 int is_mcast(struct ip_addr* ip);
260 #endif /* USE_MCAST */
261
262 /* returns 1 if the given ip address is INADDR_ANY or IN6ADDR_ANY,
263  * 0 otherwise */
264 inline static int ip_addr_any(struct ip_addr* ip)
265 {
266         int r;
267         int l;
268         
269         l=ip->len/4;
270         for (r=0; r<l; r++)
271                 if (ip->u.addr32[r]!=0)
272                         return 0;
273         return 1;
274 }
275
276
277
278 /* returns 1 if the given ip address is a loopback address
279  * 0 otherwise */
280 inline static int ip_addr_loopback(struct ip_addr* ip)
281 {
282         if (ip->af==AF_INET)
283                 return ip->u.addr32[0]==htonl(INADDR_LOOPBACK);
284 #ifdef USE_IPV6
285         else if (ip->af==AF_INET6)
286                 return IN6_IS_ADDR_LOOPBACK((struct in6_addr*)ip->u.addr32);
287 #endif /* USE_IPV6 */
288         return 0;
289 }
290
291
292
293 /* creates an ANY ip_addr (filled with 0, af and len properly set) */
294 inline static void ip_addr_mk_any(int af, struct ip_addr* ip)
295 {
296         ip->af=af;
297         if (likely(af==AF_INET)){
298                 ip->len=4;
299                 ip->u.addr32[0]=0;
300         }
301 #ifdef USE_IPV6
302         else{
303                 ip->len=16;
304 #if (defined (ULONG_MAX) && ULONG_MAX > 4294967295) || defined LP64
305                 /* long is 64 bits */
306                 ip->u.addrl[0]=0;
307                 ip->u.addrl[1]=0;
308 #else
309                 ip->u.addr32[0]=0;
310                 ip->u.addr32[1]=0;
311                 ip->u.addr32[2]=0;
312                 ip->u.addr32[3]=0;
313 #endif /* ULONG_MAX */
314         }
315 #endif
316 }
317
318 /* returns 1 if ip & net.mask == net.ip ; 0 otherwise & -1 on error 
319         [ diff. address families ]) */
320 inline static int matchnet(struct ip_addr* ip, struct net* net)
321 {
322         unsigned int r;
323
324         if (ip->af == net->ip.af){
325                 for(r=0; r<ip->len/4; r++){ /* ipv4 & ipv6 addresses are
326                                                                            all multiple of 4*/
327                         if ((ip->u.addr32[r]&net->mask.u.addr32[r])!=
328                                                                                                                  net->ip.u.addr32[r]){
329                                 return 0;
330                         }
331                 }
332                 return 1;
333         };
334         return -1;
335 }
336
337
338
339
340 /* inits an ip_addr pointer from a sockaddr structure*/
341 static inline void sockaddr2ip_addr(struct ip_addr* ip, struct sockaddr* sa)
342 {
343         switch(sa->sa_family){
344         case AF_INET:
345                         ip->af=AF_INET;
346                         ip->len=4;
347                         memcpy(ip->u.addr, &((struct sockaddr_in*)sa)->sin_addr, 4);
348                         break;
349 #ifdef USE_IPV6
350         case AF_INET6:
351                         ip->af=AF_INET6;
352                         ip->len=16;
353                         memcpy(ip->u.addr, &((struct sockaddr_in6*)sa)->sin6_addr, 16);
354                         break;
355 #endif
356         default:
357                         LOG(L_CRIT, "sockaddr2ip_addr: BUG: unknown address family %d\n",
358                                         sa->sa_family);
359         }
360 }
361
362
363
364 /* compare 2 ip_addrs (both args are pointers)*/
365 #define ip_addr_cmp(ip1, ip2) \
366         (((ip1)->af==(ip2)->af)&& \
367                 (memcmp((ip1)->u.addr, (ip2)->u.addr, (ip1)->len)==0))
368
369
370
371 /* compare 2 sockaddr_unions */
372 static inline int su_cmp(const union sockaddr_union* s1,
373                                                  const union sockaddr_union* s2)
374 {
375         if (s1->s.sa_family!=s2->s.sa_family) return 0;
376         switch(s1->s.sa_family){
377                 case AF_INET:
378                         return (s1->sin.sin_port==s2->sin.sin_port)&&
379                                         (memcmp(&s1->sin.sin_addr, &s2->sin.sin_addr, 4)==0);
380 #ifdef USE_IPV6
381                 case AF_INET6:
382                         return (s1->sin6.sin6_port==s2->sin6.sin6_port)&&
383                                         (memcmp(&s1->sin6.sin6_addr, &s2->sin6.sin6_addr, 16)==0);
384 #endif
385                 default:
386                         LOG(L_CRIT,"su_cmp: BUG: unknown address family %d\n",
387                                                 s1->s.sa_family);
388                         return 0;
389         }
390 }
391
392
393
394 /* gets the port number (host byte order) */
395 static inline unsigned short su_getport(const union sockaddr_union* su)
396 {
397         switch(su->s.sa_family){
398                 case AF_INET:
399                         return ntohs(su->sin.sin_port);
400 #ifdef USE_IPV6
401                 case AF_INET6:
402                         return ntohs(su->sin6.sin6_port);
403 #endif
404                 default:
405                         LOG(L_CRIT,"su_get_port: BUG: unknown address family %d\n",
406                                                 su->s.sa_family);
407                         return 0;
408         }
409 }
410
411
412
413 /* sets the port number (host byte order) */
414 static inline void su_setport(union sockaddr_union* su, unsigned short port)
415 {
416         switch(su->s.sa_family){
417                 case AF_INET:
418                         su->sin.sin_port=htons(port);
419                         break;
420 #ifdef USE_IPV6
421                 case AF_INET6:
422                          su->sin6.sin6_port=htons(port);
423                          break;
424 #endif
425                 default:
426                         LOG(L_CRIT,"su_set_port: BUG: unknown address family %d\n",
427                                                 su->s.sa_family);
428         }
429 }
430
431
432
433 /* inits an ip_addr pointer from a sockaddr_union ip address */
434 static inline void su2ip_addr(struct ip_addr* ip, union sockaddr_union* su)
435 {
436         switch(su->s.sa_family){
437         case AF_INET: 
438                                         ip->af=AF_INET;
439                                         ip->len=4;
440                                         memcpy(ip->u.addr, &su->sin.sin_addr, 4);
441                                         break;
442 #ifdef USE_IPV6
443         case AF_INET6:
444                                         ip->af=AF_INET6;
445                                         ip->len=16;
446                                         memcpy(ip->u.addr, &su->sin6.sin6_addr, 16);
447                                         break;
448 #endif
449         default:
450                                         LOG(L_CRIT,"su2ip_addr: BUG: unknown address family %d\n",
451                                                         su->s.sa_family);
452         }
453 }
454
455
456 /* ip_addr2su -> the same as init_su*/
457 #define ip_addr2su init_su
458
459 /* inits a struct sockaddr_union from a struct ip_addr and a port no 
460  * returns 0 if ok, -1 on error (unknown address family)
461  * the port number is in host byte order */
462 static inline int init_su( union sockaddr_union* su,
463                                                         struct ip_addr* ip,
464                                                         unsigned short   port ) 
465 {
466         memset(su, 0, sizeof(union sockaddr_union));/*needed on freebsd*/
467         su->s.sa_family=ip->af;
468         switch(ip->af){
469 #ifdef USE_IPV6
470         case    AF_INET6:
471                 memcpy(&su->sin6.sin6_addr, ip->u.addr, ip->len); 
472                 #ifdef HAVE_SOCKADDR_SA_LEN
473                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
474                 #endif
475                 su->sin6.sin6_port=htons(port);
476                 break;
477 #endif
478         case AF_INET:
479                 memcpy(&su->sin.sin_addr, ip->u.addr, ip->len);
480                 #ifdef HAVE_SOCKADDR_SA_LEN
481                         su->sin.sin_len=sizeof(struct sockaddr_in);
482                 #endif
483                 su->sin.sin_port=htons(port);
484                 break;
485         default:
486                 LOG(L_CRIT, "init_ss: BUG: unknown address family %d\n", ip->af);
487                 return -1;
488         }
489         return 0;
490 }
491
492
493
494 /* inits a struct sockaddr_union from a struct hostent, an address index in
495  * the hostent structure and a port no. (host byte order)
496  * WARNING: no index overflow  checks!
497  * returns 0 if ok, -1 on error (unknown address family) */
498 static inline int hostent2su( union sockaddr_union* su,
499                                                                 struct hostent* he,
500                                                                 unsigned int idx,
501                                                                 unsigned short   port ) 
502 {
503         memset(su, 0, sizeof(union sockaddr_union)); /*needed on freebsd*/
504         su->s.sa_family=he->h_addrtype;
505         switch(he->h_addrtype){
506 #ifdef USE_IPV6
507         case    AF_INET6:
508                 memcpy(&su->sin6.sin6_addr, he->h_addr_list[idx], he->h_length);
509                 #ifdef HAVE_SOCKADDR_SA_LEN
510                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
511                 #endif
512                 su->sin6.sin6_port=htons(port);
513                 break;
514 #endif
515         case AF_INET:
516                 memcpy(&su->sin.sin_addr, he->h_addr_list[idx], he->h_length);
517                 #ifdef HAVE_SOCKADDR_SA_LEN
518                         su->sin.sin_len=sizeof(struct sockaddr_in);
519                 #endif
520                 su->sin.sin_port=htons(port);
521                 break;
522         default:
523                 LOG(L_CRIT, "hostent2su: BUG: unknown address family %d\n", 
524                                 he->h_addrtype);
525                 return -1;
526         }
527         return 0;
528 }
529
530
531
532 /* maximum size of a str returned by ip_addr2str */
533 #define IP6_MAX_STR_SIZE 39 /*1234:5678:9012:3456:7890:1234:5678:9012*/
534 #define IP4_MAX_STR_SIZE 15 /*123.456.789.012*/
535
536 #ifdef USE_IPV6
537 /* converts a raw ipv6 addr (16 bytes) to ascii */
538 static inline int ip6tosbuf(unsigned char* ip6, char* buff, int len)
539 {
540         int offset;
541         register unsigned char a,b,c;
542         register unsigned char d;
543         register unsigned short hex4;
544         int r;
545         #define HEXDIG(x) (((x)>=10)?(x)-10+'A':(x)+'0')
546         
547         
548         offset=0;
549         if (unlikely(len<IP6_MAX_STR_SIZE))
550                 return 0;
551         for(r=0;r<7;r++){
552                 hex4=((unsigned char)ip6[r*2]<<8)+(unsigned char)ip6[r*2+1];
553                 a=hex4>>12;
554                 b=(hex4>>8)&0xf;
555                 c=(hex4>>4)&0xf;
556                 d=hex4&0xf;
557                 if (a){
558                         buff[offset]=HEXDIG(a);
559                         buff[offset+1]=HEXDIG(b);
560                         buff[offset+2]=HEXDIG(c);
561                         buff[offset+3]=HEXDIG(d);
562                         buff[offset+4]=':';
563                         offset+=5;
564                 }else if(b){
565                         buff[offset]=HEXDIG(b);
566                         buff[offset+1]=HEXDIG(c);
567                         buff[offset+2]=HEXDIG(d);
568                         buff[offset+3]=':';
569                         offset+=4;
570                 }else if(c){
571                         buff[offset]=HEXDIG(c);
572                         buff[offset+1]=HEXDIG(d);
573                         buff[offset+2]=':';
574                         offset+=3;
575                 }else{
576                         buff[offset]=HEXDIG(d);
577                         buff[offset+1]=':';
578                         offset+=2;
579                 }
580         }
581         /* last int16*/
582         hex4=((unsigned char)ip6[r*2]<<8)+(unsigned char)ip6[r*2+1];
583         a=hex4>>12;
584         b=(hex4>>8)&0xf;
585         c=(hex4>>4)&0xf;
586         d=hex4&0xf;
587         if (a){
588                 buff[offset]=HEXDIG(a);
589                 buff[offset+1]=HEXDIG(b);
590                 buff[offset+2]=HEXDIG(c);
591                 buff[offset+3]=HEXDIG(d);
592                 offset+=4;
593         }else if(b){
594                 buff[offset]=HEXDIG(b);
595                 buff[offset+1]=HEXDIG(c);
596                 buff[offset+2]=HEXDIG(d);
597                 offset+=3;
598         }else if(c){
599                 buff[offset]=HEXDIG(c);
600                 buff[offset+1]=HEXDIG(d);
601                 offset+=2;
602         }else{
603                 buff[offset]=HEXDIG(d);
604                 offset+=1;
605         }
606         
607         return offset;
608 }
609 #endif /* USE_IPV6 */
610
611
612
613 /* converts a raw ipv4 addr (4 bytes) to ascii */
614 static inline int ip4tosbuf(unsigned char* ip4, char* buff, int len)
615 {
616         int offset;
617         register unsigned char a,b,c;
618         int r;
619         
620         
621         offset=0;
622         if (unlikely(len<IP4_MAX_STR_SIZE))
623                 return 0;
624         for(r=0;r<3;r++){
625                 a=(unsigned char)ip4[r]/100;
626                 c=(unsigned char)ip4[r]%10;
627                 b=(unsigned char)ip4[r]%100/10;
628                 if (a){
629                         buff[offset]=a+'0';
630                         buff[offset+1]=b+'0';
631                         buff[offset+2]=c+'0';
632                         buff[offset+3]='.';
633                         offset+=4;
634                 }else if (b){
635                         buff[offset]=b+'0';
636                         buff[offset+1]=c+'0';
637                         buff[offset+2]='.';
638                         offset+=3;
639                 }else{
640                         buff[offset]=c+'0';
641                         buff[offset+1]='.';
642                         offset+=2;
643                 }
644         }
645         /* last number */
646         a=(unsigned char)ip4[r]/100;
647         c=(unsigned char)ip4[r]%10;
648         b=(unsigned char)ip4[r]%100/10;
649         if (a){
650                 buff[offset]=a+'0';
651                 buff[offset+1]=b+'0';
652                 buff[offset+2]=c+'0';
653                 offset+=3;
654         }else if (b){
655                 buff[offset]=b+'0';
656                 buff[offset+1]=c+'0';
657                 offset+=2;
658         }else{
659                 buff[offset]=c+'0';
660                 offset+=1;
661         }
662         
663         return offset;
664 }
665
666
667
668 /* fast ip_addr -> string converter;
669  * returns number of bytes written in buf on success, <=0 on error
670  * The buffer must have enough space to hold the maximum size ip address
671  *  of the corresponding address (see IP[46] above) or else the function
672  *  will return error (no detailed might fit checks are made, for example
673  *   if len==7 the function will fail even for 1.2.3.4).
674  */
675 static inline int ip_addr2sbuf(struct ip_addr* ip, char* buff, int len)
676 {
677         switch(ip->af){
678         #ifdef USE_IPV6
679                 case AF_INET6:
680                         return ip6tosbuf(ip->u.addr, buff, len);
681                         break;
682         #endif /* USE_IPV6 */
683                 case AF_INET:
684                         return ip4tosbuf(ip->u.addr, buff, len);
685                         break;
686                 default:
687                         LOG(L_CRIT, "BUG: ip_addr2sbuf: unknown address family %d\n",
688                                         ip->af);
689                         return 0;
690         }
691         return 0;
692 }
693
694
695
696 /* maximum size of a str returned by ip_addr2a (including \0) */
697 #define IP_ADDR_MAX_STR_SIZE (IP6_MAX_STR_SIZE+1) /* ip62ascii +  \0*/
698 /* fast ip_addr -> string converter;
699  * it uses an internal buffer
700  */
701 static inline char* ip_addr2a(struct ip_addr* ip)
702 {
703
704         static char buff[IP_ADDR_MAX_STR_SIZE];
705         int len;
706         
707         
708         len=ip_addr2sbuf(ip, buff, sizeof(buff)-1);
709         buff[len]=0;
710
711         return buff;
712 }
713
714
715
716 #define SU2A_MAX_STR_SIZE  (IP6_MAX_STR_SIZE + 2 /* [] */+\
717                                                                 1 /* : */ + USHORT2SBUF_MAX_LEN + 1 /* \0 */)
718 /* returns an asciiz string containing the ip and the port
719  *  (<ip_addr>:port or [<ipv6_addr>]:port)
720  */
721 static inline char* su2a(union sockaddr_union* su, int su_len)
722 {
723         static char buf[SU2A_MAX_STR_SIZE];
724         int offs;
725
726 #ifdef USE_IPV6
727         if (unlikely(su->s.sa_family==AF_INET6)){
728                 if (unlikely(su_len<sizeof(su->sin6)))
729                         return "<addr. error>";
730                 buf[0]='[';
731                 offs=1+ip6tosbuf((unsigned char*)su->sin6.sin6_addr.s6_addr, &buf[1],
732                                                         sizeof(buf)-4);
733                 buf[offs]=']';
734                 offs++;
735         }else
736 #endif /* USE_IPV6*/
737         if (unlikely(su_len<sizeof(su->sin)))
738                 return "<addr. error>";
739         else
740                 offs=ip4tosbuf((unsigned char*)&su->sin.sin_addr, buf, sizeof(buf)-2);
741         buf[offs]=':';
742         offs+=1+ushort2sbuf(su_getport(su), &buf[offs+1], sizeof(buf)-(offs+1)-1);
743         buf[offs]=0;
744         return buf;
745 }
746
747 #define SUIP2A_MAX_STR_SIZE  (IP6_MAX_STR_SIZE + 2 /* [] */ + 1 /* \0 */)
748 /* returns an asciiz string containing the ip
749  *  (<ipv4_addr> or [<ipv6_addr>])
750  */
751 static inline char* suip2a(union sockaddr_union* su, int su_len)
752 {
753         static char buf[SUIP2A_MAX_STR_SIZE];
754         int offs;
755
756 #ifdef USE_IPV6
757         if (unlikely(su->s.sa_family==AF_INET6)){
758                 if (unlikely(su_len<sizeof(su->sin6)))
759                         return "<addr. error>";
760                 buf[0]='[';
761                 offs=1+ip6tosbuf((unsigned char*)su->sin6.sin6_addr.s6_addr, &buf[1],
762                                                         sizeof(buf)-4);
763                 buf[offs]=']';
764                 offs++;
765         }else
766 #endif /* USE_IPV6*/
767         if (unlikely(su_len<sizeof(su->sin)))
768                 return "<addr. error>";
769         else
770                 offs=ip4tosbuf((unsigned char*)&su->sin.sin_addr, buf, sizeof(buf)-2);
771         buf[offs]=0;
772         return buf;
773 }
774
775
776
777 /* converts an ip_addr structure to a hostent, returns pointer to internal
778  * statical structure */
779 static inline struct hostent* ip_addr2he(str* name, struct ip_addr* ip)
780 {
781         static struct hostent he;
782         static char hostname[256];
783         static char* p_aliases[1];
784         static char* p_addr[2];
785         static char address[16];
786         
787         p_aliases[0]=0; /* no aliases*/
788         p_addr[1]=0; /* only one address*/
789         p_addr[0]=address;
790         strncpy(hostname, name->s, (name->len<256)?(name->len)+1:256);
791         if (ip->len>16) return 0;
792         memcpy(address, ip->u.addr, ip->len);
793         
794         he.h_addrtype=ip->af;
795         he.h_length=ip->len;
796         he.h_addr_list=p_addr;
797         he.h_aliases=p_aliases;
798         he.h_name=hostname;
799         return &he;
800 }
801
802
803
804 /* init a dest_info structure */
805 #define init_dest_info(dst) \
806         do{ \
807                 memset((dst), 0, sizeof(struct dest_info)); \
808         } while(0) 
809
810
811
812 /* init a dest_info structure from a recv_info structure */
813 inline static void init_dst_from_rcv(struct dest_info* dst,
814                                                                         struct receive_info* rcv)
815 {
816                 dst->send_sock=rcv->bind_address;
817                 dst->to=rcv->src_su;
818                 dst->id=rcv->proto_reserved1;
819                 dst->proto=rcv->proto;
820                 dst->send_flags.f=0;
821                 dst->send_flags.blst_imask=0;
822 #ifdef USE_COMP
823                 dst->comp=rcv->comp;
824 #endif
825 }
826
827
828 #endif