• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • Directories
  • File List
  • Globals

ip_addr.h

00001 /* $Id$
00002  *
00003  * ip address family related structures
00004  *
00005  * Copyright (C) 2001-2003 FhG Fokus
00006  *
00007  * This file is part of ser, a free SIP server.
00008  *
00009  * ser is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version
00013  *
00014  * For a license to use the ser software under conditions
00015  * other than those described here, or to purchase support for this
00016  * software, please contact iptel.org by e-mail at the following addresses:
00017  *    info@iptel.org
00018  *
00019  * ser is distributed in the hope that it will be useful,
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022  * GNU General Public License for more details.
00023  *
00024  * You should have received a copy of the GNU General Public License 
00025  * along with this program; if not, write to the Free Software 
00026  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00027  */
00028 /*
00029  * History:
00030  * --------
00031  *  2003-02-13  added struct dest_info (andrei)
00032  *  2003-04-06  all ports are stored/passed in host byte order now (andrei)
00033  *  2006-04-20  comp support in recv_info and dest_info (andrei)
00034  *  2006-04-21  added init_dst_from_rcv (andrei)
00035  *  2007-06-26  added ip_addr_mk_any() (andrei)
00036  *  2008-05-21  added su2a(), ip_addr2sbuf(), ip4tosbuf(), ip62sbuf() (andrei)
00037  *  2009-09-14  added send flags support to dest_info (andrei)
00038  */
00039 
00040 #ifndef ip_addr_h
00041 #define ip_addr_h
00042 
00043 #include <string.h>
00044 #include <sys/types.h>
00045 #include <sys/socket.h>
00046 #include <netinet/in.h>
00047 #include <netdb.h>
00048 #include "str.h"
00049 #include "compiler_opt.h"
00050 #include "ut.h"
00051 
00052 
00053 #include "dprint.h"
00054 
00055 enum sip_protos { PROTO_NONE, PROTO_UDP, PROTO_TCP, PROTO_TLS, PROTO_SCTP, PROTO_OTHER };
00056 #define PROTO_LAST PROTO_OTHER
00057 
00058 #ifdef USE_COMP
00059 enum comp_methods { COMP_NONE, COMP_SIGCOMP, COMP_SERGZ };
00060 #endif
00061 
00062 struct ip_addr{
00063         unsigned int af; /* address family: AF_INET6 or AF_INET */
00064         unsigned int len;    /* address len, 16 or 4 */
00065         
00066         /* 64 bits aligned address */
00067         union {
00068                 unsigned long  addrl[16/sizeof(long)]; /* long format*/
00069                 unsigned int   addr32[4];
00070                 unsigned short addr16[8];
00071                 unsigned char  addr[16];
00072         }u;
00073 };
00074 
00075 typedef struct ip_addr ip_addr_t;
00076 
00077 struct net{
00078         struct ip_addr ip;
00079         struct ip_addr mask;
00080 };
00081 
00082 union sockaddr_union{
00083                 struct sockaddr     s;
00084                 struct sockaddr_in  sin;
00085         #ifdef USE_IPV6
00086                 struct sockaddr_in6 sin6;
00087         #endif
00088 };
00089 
00090 
00091 
00092 enum si_flags { SI_NONE=0, SI_IS_IP=1, SI_IS_LO=2, SI_IS_MCAST=4,
00093                                  SI_IS_ANY=8, SI_IS_MHOMED=16 };
00094 
00095 struct addr_info{
00096         str name; /* name - eg.: foo.bar or 10.0.0.1 */
00097         struct ip_addr address; /*ip address */
00098         str address_str;        /*ip address converted to string -- optimization*/
00099         enum si_flags flags; /* SI_IS_IP | SI_IS_LO | SI_IS_MCAST */
00100         union sockaddr_union su;
00101         struct addr_info* next;
00102         struct addr_info* prev;
00103 };
00104 
00105 struct advertise_info {
00106         str name; /* name - eg.: foo.bar or 10.0.0.1 */
00107         unsigned short port_no;  /* port number */
00108         str port_no_str; /* port number converted to string -- optimization*/
00109         str address_str;        /*ip address converted to string -- optimization*/
00110         struct ip_addr address; /* ip address */
00111         str sock_str; /* Socket proto, ip, and port as string */
00112 };
00113 
00114 struct socket_info{
00115         int socket;
00116         str name; /* name - eg.: foo.bar or 10.0.0.1 */
00117         struct ip_addr address; /* ip address */
00118         str address_str;        /*ip address converted to string -- optimization*/
00119         str port_no_str; /* port number converted to string -- optimization*/
00120         enum si_flags flags; /* SI_IS_IP | SI_IS_LO | SI_IS_MCAST */
00121         union sockaddr_union su; 
00122         struct socket_info* next;
00123         struct socket_info* prev;
00124         unsigned short port_no;  /* port number */
00125         char proto; /* tcp or udp*/
00126         str sock_str; /* Socket proto, ip, and port as string */
00127         struct addr_info* addr_info_lst; /* extra addresses (e.g. SCTP mh) */
00128         int workers; /* number of worker processes for this socket */
00129         int workers_tcpidx; /* index of workers in tcp children array */
00130         struct advertise_info useinfo; /* details to be used in SIP msg */
00131 };
00132 
00133 
00134 struct receive_info{
00135         struct ip_addr src_ip;
00136         struct ip_addr dst_ip;
00137         unsigned short src_port; /* host byte order */
00138         unsigned short dst_port; /* host byte order */
00139         int proto_reserved1; /* tcp stores the connection id here */
00140         int proto_reserved2;
00141         union sockaddr_union src_su; /* useful for replies*/
00142         struct socket_info* bind_address; /* sock_info structure on which 
00143                                                                           the msg was received*/
00144         char proto;
00145 #ifdef USE_COMP
00146         short comp; /* compression */
00147 #endif
00148         /* no need for dst_su yet */
00149 };
00150 
00151 
00152 /* send flags */
00153 #define SND_F_FORCE_CON_REUSE   1 /* reuse an existing connection or fail */
00154 #define SND_F_CON_CLOSE                 2 /* close the connection after sending */
00155 #define SND_F_FORCE_SOCKET              4 /* send socket in dst is forced */
00156 
00157 struct snd_flags {
00158         unsigned char f;          /* snd flags */
00159         unsigned char blst_imask; /* blacklist ignore mask */
00160 };
00161 
00162 
00163 typedef struct snd_flags  snd_flags_t;
00164 
00165 #define SND_FLAGS_INIT(sflags) \
00166         do{ \
00167                 (sflags)->f=0; \
00168                 (sflags)->blst_imask=0; \
00169         }while(0)
00170 
00171 #define SND_FLAGS_OR(dst, src1, src2) \
00172         do{ \
00173                 (dst)->f = (src1)->f | (src2)->f; \
00174                 (dst)->blst_imask = (src1)->blst_imask | (src2)->blst_imask; \
00175         }while(0)
00176 
00177 #define SND_FLAGS_AND(dst, src1, src2) \
00178         do{ \
00179                 (dst)->f = (src1)->f & (src2)->f; \
00180                 (dst)->blst_imask = (src1)->blst_imask & (src2)->blst_imask; \
00181         }while(0)
00182 
00183 struct dest_info{
00184         struct socket_info* send_sock;
00185         union sockaddr_union to;
00186         int id; /* tcp stores the connection id here */ 
00187         char proto;
00188         snd_flags_t send_flags;
00189 #ifdef USE_COMP
00190         short comp;
00191 #endif
00192 };
00193 
00194 
00195 /* list of names for multi-homed sockets that need to bind on
00196  * multiple addresses in the same time (sctp ) */
00197 struct name_lst{
00198         char* name;
00199         struct name_lst* next;
00200         int flags;
00201 };
00202 
00203 
00204 struct socket_id{
00205         struct name_lst* addr_lst; /* address list, the first one must
00206                                                                   be present and is the main one
00207                                                                   (in case of multihoming sctp)*/
00208         int flags;
00209         int proto;
00210         int port;
00211         struct socket_id* next;
00212 };
00213 
00214 
00215 
00216 /* len of the sockaddr */
00217 #ifdef HAVE_SOCKADDR_SA_LEN
00218 #define sockaddru_len(su)       ((su).s.sa_len)
00219 #else
00220 #ifdef USE_IPV6
00221 #define sockaddru_len(su)       \
00222                         (((su).s.sa_family==AF_INET6)?sizeof(struct sockaddr_in6):\
00223                                         sizeof(struct sockaddr_in))
00224 #else
00225 #define sockaddru_len(su)       sizeof(struct sockaddr_in)
00226 #endif /*USE_IPV6*/
00227 #endif /* HAVE_SOCKADDR_SA_LEN*/
00228         
00229 /* inits an ip_addr with the addr. info from a hostent structure
00230  * ip = struct ip_addr*
00231  * he= struct hostent*
00232  */
00233 #define hostent2ip_addr(ip, he, addr_no) \
00234         do{ \
00235                 (ip)->af=(he)->h_addrtype; \
00236                 (ip)->len=(he)->h_length;  \
00237                 memcpy((ip)->u.addr, (he)->h_addr_list[(addr_no)], (ip)->len); \
00238         }while(0)
00239         
00240 
00241 
00242 
00243 /* gets the protocol family corresponding to a specific address family
00244  * ( PF_INET - AF_INET, PF_INET6 - AF_INET6, af for others)
00245  */
00246 #ifdef USE_IPV6
00247 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:((af)==AF_INET6)?PF_INET6:(af))
00248 #else
00249 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:(af))
00250 #endif
00251 
00252 
00253 
00254 
00255 struct net* mk_new_net(struct ip_addr* ip, struct ip_addr* mask);
00256 struct net* mk_new_net_bitlen(struct ip_addr* ip, unsigned int bitlen);
00257 int mk_net(struct net* n, struct ip_addr* ip, struct ip_addr* mask);
00258 int mk_net_bitlen(struct net* n, struct ip_addr* ip, unsigned int bitlen);
00259 int mk_net_str(struct net* dst, str* s);
00260 
00261 void print_ip(char* prefix, struct ip_addr* ip, char* suffix);
00262 void stdout_print_ip(struct ip_addr* ip);
00263 void print_net(struct net* net);
00264 
00265 char* get_proto_name(unsigned int proto);
00266 #define proto2a get_proto_name
00267 
00268 
00269 
00270 #ifdef USE_MCAST
00271 /* Returns 1 if the given address is a multicast address */
00272 int is_mcast(struct ip_addr* ip);
00273 #endif /* USE_MCAST */
00274 
00275 /* returns 1 if the given ip address is INADDR_ANY or IN6ADDR_ANY,
00276  * 0 otherwise */
00277 inline static int ip_addr_any(struct ip_addr* ip)
00278 {
00279         int r;
00280         int l;
00281         
00282         l=ip->len/4;
00283         for (r=0; r<l; r++)
00284                 if (ip->u.addr32[r]!=0)
00285                         return 0;
00286         return 1;
00287 }
00288 
00289 
00290 
00291 /* returns 1 if the given ip address is a loopback address
00292  * 0 otherwise */
00293 inline static int ip_addr_loopback(struct ip_addr* ip)
00294 {
00295         if (ip->af==AF_INET)
00296                 return ip->u.addr32[0]==htonl(INADDR_LOOPBACK);
00297 #ifdef USE_IPV6
00298         else if (ip->af==AF_INET6)
00299                 return IN6_IS_ADDR_LOOPBACK((struct in6_addr*)ip->u.addr32);
00300 #endif /* USE_IPV6 */
00301         return 0;
00302 }
00303 
00304 
00305 
00306 /* creates an ANY ip_addr (filled with 0, af and len properly set) */
00307 inline static void ip_addr_mk_any(int af, struct ip_addr* ip)
00308 {
00309         ip->af=af;
00310         if (likely(af==AF_INET)){
00311                 ip->len=4;
00312                 ip->u.addr32[0]=0;
00313         }
00314 #ifdef USE_IPV6
00315         else{
00316                 ip->len=16;
00317 #if (defined (ULONG_MAX) && ULONG_MAX > 4294967295) || defined LP64
00318                 /* long is 64 bits */
00319                 ip->u.addrl[0]=0;
00320                 ip->u.addrl[1]=0;
00321 #else
00322                 ip->u.addr32[0]=0;
00323                 ip->u.addr32[1]=0;
00324                 ip->u.addr32[2]=0;
00325                 ip->u.addr32[3]=0;
00326 #endif /* ULONG_MAX */
00327         }
00328 #endif
00329 }
00330 
00331 /* returns 1 if ip & net.mask == net.ip ; 0 otherwise & -1 on error 
00332         [ diff. address families ]) */
00333 inline static int matchnet(struct ip_addr* ip, struct net* net)
00334 {
00335         unsigned int r;
00336 
00337         if (ip->af == net->ip.af){
00338                 for(r=0; r<ip->len/4; r++){ /* ipv4 & ipv6 addresses are
00339                                                                            all multiple of 4*/
00340                         if ((ip->u.addr32[r]&net->mask.u.addr32[r])!=
00341                                                                                                                  net->ip.u.addr32[r]){
00342                                 return 0;
00343                         }
00344                 }
00345                 return 1;
00346         };
00347         return -1;
00348 }
00349 
00350 
00351 
00352 
00353 /* inits an ip_addr pointer from a sockaddr structure*/
00354 static inline void sockaddr2ip_addr(struct ip_addr* ip, struct sockaddr* sa)
00355 {
00356         switch(sa->sa_family){
00357         case AF_INET:
00358                         ip->af=AF_INET;
00359                         ip->len=4;
00360                         memcpy(ip->u.addr, &((struct sockaddr_in*)sa)->sin_addr, 4);
00361                         break;
00362 #ifdef USE_IPV6
00363         case AF_INET6:
00364                         ip->af=AF_INET6;
00365                         ip->len=16;
00366                         memcpy(ip->u.addr, &((struct sockaddr_in6*)sa)->sin6_addr, 16);
00367                         break;
00368 #endif
00369         default:
00370                         LOG(L_CRIT, "sockaddr2ip_addr: BUG: unknown address family %d\n",
00371                                         sa->sa_family);
00372         }
00373 }
00374 
00375 
00376 
00377 /* compare 2 ip_addrs (both args are pointers)*/
00378 #define ip_addr_cmp(ip1, ip2) \
00379         (((ip1)->af==(ip2)->af)&& \
00380                 (memcmp((ip1)->u.addr, (ip2)->u.addr, (ip1)->len)==0))
00381 
00382 
00383 
00384 /* compare 2 sockaddr_unions */
00385 static inline int su_cmp(const union sockaddr_union* s1,
00386                                                  const union sockaddr_union* s2)
00387 {
00388         if (s1->s.sa_family!=s2->s.sa_family) return 0;
00389         switch(s1->s.sa_family){
00390                 case AF_INET:
00391                         return (s1->sin.sin_port==s2->sin.sin_port)&&
00392                                         (memcmp(&s1->sin.sin_addr, &s2->sin.sin_addr, 4)==0);
00393 #ifdef USE_IPV6
00394                 case AF_INET6:
00395                         return (s1->sin6.sin6_port==s2->sin6.sin6_port)&&
00396                                         (memcmp(&s1->sin6.sin6_addr, &s2->sin6.sin6_addr, 16)==0);
00397 #endif
00398                 default:
00399                         LOG(L_CRIT,"su_cmp: BUG: unknown address family %d\n",
00400                                                 s1->s.sa_family);
00401                         return 0;
00402         }
00403 }
00404 
00405 
00406 
00407 /* gets the port number (host byte order) */
00408 static inline unsigned short su_getport(const union sockaddr_union* su)
00409 {
00410         switch(su->s.sa_family){
00411                 case AF_INET:
00412                         return ntohs(su->sin.sin_port);
00413 #ifdef USE_IPV6
00414                 case AF_INET6:
00415                         return ntohs(su->sin6.sin6_port);
00416 #endif
00417                 default:
00418                         LOG(L_CRIT,"su_get_port: BUG: unknown address family %d\n",
00419                                                 su->s.sa_family);
00420                         return 0;
00421         }
00422 }
00423 
00424 
00425 
00426 /* sets the port number (host byte order) */
00427 static inline void su_setport(union sockaddr_union* su, unsigned short port)
00428 {
00429         switch(su->s.sa_family){
00430                 case AF_INET:
00431                         su->sin.sin_port=htons(port);
00432                         break;
00433 #ifdef USE_IPV6
00434                 case AF_INET6:
00435                          su->sin6.sin6_port=htons(port);
00436                          break;
00437 #endif
00438                 default:
00439                         LOG(L_CRIT,"su_set_port: BUG: unknown address family %d\n",
00440                                                 su->s.sa_family);
00441         }
00442 }
00443 
00444 
00445 
00446 /* inits an ip_addr pointer from a sockaddr_union ip address */
00447 static inline void su2ip_addr(struct ip_addr* ip, union sockaddr_union* su)
00448 {
00449         switch(su->s.sa_family){
00450         case AF_INET: 
00451                                         ip->af=AF_INET;
00452                                         ip->len=4;
00453                                         memcpy(ip->u.addr, &su->sin.sin_addr, 4);
00454                                         break;
00455 #ifdef USE_IPV6
00456         case AF_INET6:
00457                                         ip->af=AF_INET6;
00458                                         ip->len=16;
00459                                         memcpy(ip->u.addr, &su->sin6.sin6_addr, 16);
00460                                         break;
00461 #endif
00462         default:
00463                                         LOG(L_CRIT,"su2ip_addr: BUG: unknown address family %d\n",
00464                                                         su->s.sa_family);
00465         }
00466 }
00467 
00468 
00469 /* ip_addr2su -> the same as init_su*/
00470 #define ip_addr2su init_su
00471 
00472 /* inits a struct sockaddr_union from a struct ip_addr and a port no 
00473  * returns 0 if ok, -1 on error (unknown address family)
00474  * the port number is in host byte order */
00475 static inline int init_su( union sockaddr_union* su,
00476                                                         struct ip_addr* ip,
00477                                                         unsigned short   port ) 
00478 {
00479         memset(su, 0, sizeof(union sockaddr_union));/*needed on freebsd*/
00480         su->s.sa_family=ip->af;
00481         switch(ip->af){
00482 #ifdef USE_IPV6
00483         case    AF_INET6:
00484                 memcpy(&su->sin6.sin6_addr, ip->u.addr, ip->len); 
00485                 #ifdef HAVE_SOCKADDR_SA_LEN
00486                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
00487                 #endif
00488                 su->sin6.sin6_port=htons(port);
00489                 break;
00490 #endif
00491         case AF_INET:
00492                 memcpy(&su->sin.sin_addr, ip->u.addr, ip->len);
00493                 #ifdef HAVE_SOCKADDR_SA_LEN
00494                         su->sin.sin_len=sizeof(struct sockaddr_in);
00495                 #endif
00496                 su->sin.sin_port=htons(port);
00497                 break;
00498         default:
00499                 LOG(L_CRIT, "init_ss: BUG: unknown address family %d\n", ip->af);
00500                 return -1;
00501         }
00502         return 0;
00503 }
00504 
00505 
00506 
00507 /* inits a struct sockaddr_union from a struct hostent, an address index in
00508  * the hostent structure and a port no. (host byte order)
00509  * WARNING: no index overflow  checks!
00510  * returns 0 if ok, -1 on error (unknown address family) */
00511 static inline int hostent2su( union sockaddr_union* su,
00512                                                                 struct hostent* he,
00513                                                                 unsigned int idx,
00514                                                                 unsigned short   port ) 
00515 {
00516         memset(su, 0, sizeof(union sockaddr_union)); /*needed on freebsd*/
00517         su->s.sa_family=he->h_addrtype;
00518         switch(he->h_addrtype){
00519 #ifdef USE_IPV6
00520         case    AF_INET6:
00521                 memcpy(&su->sin6.sin6_addr, he->h_addr_list[idx], he->h_length);
00522                 #ifdef HAVE_SOCKADDR_SA_LEN
00523                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
00524                 #endif
00525                 su->sin6.sin6_port=htons(port);
00526                 break;
00527 #endif
00528         case AF_INET:
00529                 memcpy(&su->sin.sin_addr, he->h_addr_list[idx], he->h_length);
00530                 #ifdef HAVE_SOCKADDR_SA_LEN
00531                         su->sin.sin_len=sizeof(struct sockaddr_in);
00532                 #endif
00533                 su->sin.sin_port=htons(port);
00534                 break;
00535         default:
00536                 LOG(L_CRIT, "hostent2su: BUG: unknown address family %d\n", 
00537                                 he->h_addrtype);
00538                 return -1;
00539         }
00540         return 0;
00541 }
00542 
00543 
00544 
00545 /* maximum size of a str returned by ip_addr2str */
00546 #define IP6_MAX_STR_SIZE 39 /*1234:5678:9012:3456:7890:1234:5678:9012*/
00547 #define IP4_MAX_STR_SIZE 15 /*123.456.789.012*/
00548 
00549 #ifdef USE_IPV6
00550 /* converts a raw ipv6 addr (16 bytes) to ascii */
00551 static inline int ip6tosbuf(unsigned char* ip6, char* buff, int len)
00552 {
00553         int offset;
00554         register unsigned char a,b,c;
00555         register unsigned char d;
00556         register unsigned short hex4;
00557         int r;
00558         #define HEXDIG(x) (((x)>=10)?(x)-10+'A':(x)+'0')
00559         
00560         
00561         offset=0;
00562         if (unlikely(len<IP6_MAX_STR_SIZE))
00563                 return 0;
00564         for(r=0;r<7;r++){
00565                 hex4=((unsigned char)ip6[r*2]<<8)+(unsigned char)ip6[r*2+1];
00566                 a=hex4>>12;
00567                 b=(hex4>>8)&0xf;
00568                 c=(hex4>>4)&0xf;
00569                 d=hex4&0xf;
00570                 if (a){
00571                         buff[offset]=HEXDIG(a);
00572                         buff[offset+1]=HEXDIG(b);
00573                         buff[offset+2]=HEXDIG(c);
00574                         buff[offset+3]=HEXDIG(d);
00575                         buff[offset+4]=':';
00576                         offset+=5;
00577                 }else if(b){
00578                         buff[offset]=HEXDIG(b);
00579                         buff[offset+1]=HEXDIG(c);
00580                         buff[offset+2]=HEXDIG(d);
00581                         buff[offset+3]=':';
00582                         offset+=4;
00583                 }else if(c){
00584                         buff[offset]=HEXDIG(c);
00585                         buff[offset+1]=HEXDIG(d);
00586                         buff[offset+2]=':';
00587                         offset+=3;
00588                 }else{
00589                         buff[offset]=HEXDIG(d);
00590                         buff[offset+1]=':';
00591                         offset+=2;
00592                 }
00593         }
00594         /* last int16*/
00595         hex4=((unsigned char)ip6[r*2]<<8)+(unsigned char)ip6[r*2+1];
00596         a=hex4>>12;
00597         b=(hex4>>8)&0xf;
00598         c=(hex4>>4)&0xf;
00599         d=hex4&0xf;
00600         if (a){
00601                 buff[offset]=HEXDIG(a);
00602                 buff[offset+1]=HEXDIG(b);
00603                 buff[offset+2]=HEXDIG(c);
00604                 buff[offset+3]=HEXDIG(d);
00605                 offset+=4;
00606         }else if(b){
00607                 buff[offset]=HEXDIG(b);
00608                 buff[offset+1]=HEXDIG(c);
00609                 buff[offset+2]=HEXDIG(d);
00610                 offset+=3;
00611         }else if(c){
00612                 buff[offset]=HEXDIG(c);
00613                 buff[offset+1]=HEXDIG(d);
00614                 offset+=2;
00615         }else{
00616                 buff[offset]=HEXDIG(d);
00617                 offset+=1;
00618         }
00619         
00620         return offset;
00621 }
00622 #endif /* USE_IPV6 */
00623 
00624 
00625 
00626 /* converts a raw ipv4 addr (4 bytes) to ascii */
00627 static inline int ip4tosbuf(unsigned char* ip4, char* buff, int len)
00628 {
00629         int offset;
00630         register unsigned char a,b,c;
00631         int r;
00632         
00633         
00634         offset=0;
00635         if (unlikely(len<IP4_MAX_STR_SIZE))
00636                 return 0;
00637         for(r=0;r<3;r++){
00638                 a=(unsigned char)ip4[r]/100;
00639                 c=(unsigned char)ip4[r]%10;
00640                 b=(unsigned char)ip4[r]%100/10;
00641                 if (a){
00642                         buff[offset]=a+'0';
00643                         buff[offset+1]=b+'0';
00644                         buff[offset+2]=c+'0';
00645                         buff[offset+3]='.';
00646                         offset+=4;
00647                 }else if (b){
00648                         buff[offset]=b+'0';
00649                         buff[offset+1]=c+'0';
00650                         buff[offset+2]='.';
00651                         offset+=3;
00652                 }else{
00653                         buff[offset]=c+'0';
00654                         buff[offset+1]='.';
00655                         offset+=2;
00656                 }
00657         }
00658         /* last number */
00659         a=(unsigned char)ip4[r]/100;
00660         c=(unsigned char)ip4[r]%10;
00661         b=(unsigned char)ip4[r]%100/10;
00662         if (a){
00663                 buff[offset]=a+'0';
00664                 buff[offset+1]=b+'0';
00665                 buff[offset+2]=c+'0';
00666                 offset+=3;
00667         }else if (b){
00668                 buff[offset]=b+'0';
00669                 buff[offset+1]=c+'0';
00670                 offset+=2;
00671         }else{
00672                 buff[offset]=c+'0';
00673                 offset+=1;
00674         }
00675         
00676         return offset;
00677 }
00678 
00679 
00680 
00681 /* fast ip_addr -> string converter;
00682  * returns number of bytes written in buf on success, <=0 on error
00683  * The buffer must have enough space to hold the maximum size ip address
00684  *  of the corresponding address (see IP[46] above) or else the function
00685  *  will return error (no detailed might fit checks are made, for example
00686  *   if len==7 the function will fail even for 1.2.3.4).
00687  */
00688 static inline int ip_addr2sbuf(struct ip_addr* ip, char* buff, int len)
00689 {
00690         switch(ip->af){
00691         #ifdef USE_IPV6
00692                 case AF_INET6:
00693                         return ip6tosbuf(ip->u.addr, buff, len);
00694                         break;
00695         #endif /* USE_IPV6 */
00696                 case AF_INET:
00697                         return ip4tosbuf(ip->u.addr, buff, len);
00698                         break;
00699                 default:
00700                         LOG(L_CRIT, "BUG: ip_addr2sbuf: unknown address family %d\n",
00701                                         ip->af);
00702                         return 0;
00703         }
00704         return 0;
00705 }
00706 
00707 
00708 
00709 /* maximum size of a str returned by ip_addr2a (including \0) */
00710 #define IP_ADDR_MAX_STR_SIZE (IP6_MAX_STR_SIZE+1) /* ip62ascii +  \0*/
00711 /* fast ip_addr -> string converter;
00712  * it uses an internal buffer
00713  */
00714 static inline char* ip_addr2a(struct ip_addr* ip)
00715 {
00716 
00717         static char buff[IP_ADDR_MAX_STR_SIZE];
00718         int len;
00719         
00720         
00721         len=ip_addr2sbuf(ip, buff, sizeof(buff)-1);
00722         buff[len]=0;
00723 
00724         return buff;
00725 }
00726 
00727 
00728 
00729 #define SU2A_MAX_STR_SIZE  (IP6_MAX_STR_SIZE + 2 /* [] */+\
00730                                                                 1 /* : */ + USHORT2SBUF_MAX_LEN + 1 /* \0 */)
00731 /* returns an asciiz string containing the ip and the port
00732  *  (<ip_addr>:port or [<ipv6_addr>]:port)
00733  */
00734 static inline char* su2a(union sockaddr_union* su, int su_len)
00735 {
00736         static char buf[SU2A_MAX_STR_SIZE];
00737         int offs;
00738 
00739 #ifdef USE_IPV6
00740         if (unlikely(su->s.sa_family==AF_INET6)){
00741                 if (unlikely(su_len<sizeof(su->sin6)))
00742                         return "<addr. error>";
00743                 buf[0]='[';
00744                 offs=1+ip6tosbuf((unsigned char*)su->sin6.sin6_addr.s6_addr, &buf[1],
00745                                                         sizeof(buf)-4);
00746                 buf[offs]=']';
00747                 offs++;
00748         }else
00749 #endif /* USE_IPV6*/
00750         if (unlikely(su_len<sizeof(su->sin)))
00751                 return "<addr. error>";
00752         else
00753                 offs=ip4tosbuf((unsigned char*)&su->sin.sin_addr, buf, sizeof(buf)-2);
00754         buf[offs]=':';
00755         offs+=1+ushort2sbuf(su_getport(su), &buf[offs+1], sizeof(buf)-(offs+1)-1);
00756         buf[offs]=0;
00757         return buf;
00758 }
00759 
00760 #define SUIP2A_MAX_STR_SIZE  (IP6_MAX_STR_SIZE + 2 /* [] */ + 1 /* \0 */)
00761 /* returns an asciiz string containing the ip
00762  *  (<ipv4_addr> or [<ipv6_addr>])
00763  */
00764 static inline char* suip2a(union sockaddr_union* su, int su_len)
00765 {
00766         static char buf[SUIP2A_MAX_STR_SIZE];
00767         int offs;
00768 
00769 #ifdef USE_IPV6
00770         if (unlikely(su->s.sa_family==AF_INET6)){
00771                 if (unlikely(su_len<sizeof(su->sin6)))
00772                         return "<addr. error>";
00773                 buf[0]='[';
00774                 offs=1+ip6tosbuf((unsigned char*)su->sin6.sin6_addr.s6_addr, &buf[1],
00775                                                         sizeof(buf)-4);
00776                 buf[offs]=']';
00777                 offs++;
00778         }else
00779 #endif /* USE_IPV6*/
00780         if (unlikely(su_len<sizeof(su->sin)))
00781                 return "<addr. error>";
00782         else
00783                 offs=ip4tosbuf((unsigned char*)&su->sin.sin_addr, buf, sizeof(buf)-2);
00784         buf[offs]=0;
00785         return buf;
00786 }
00787 
00788 
00789 
00790 /* converts an ip_addr structure to a hostent, returns pointer to internal
00791  * statical structure */
00792 static inline struct hostent* ip_addr2he(str* name, struct ip_addr* ip)
00793 {
00794         static struct hostent he;
00795         static char hostname[256];
00796         static char* p_aliases[1];
00797         static char* p_addr[2];
00798         static char address[16];
00799         
00800         p_aliases[0]=0; /* no aliases*/
00801         p_addr[1]=0; /* only one address*/
00802         p_addr[0]=address;
00803         strncpy(hostname, name->s, (name->len<256)?(name->len)+1:256);
00804         if (ip->len>16) return 0;
00805         memcpy(address, ip->u.addr, ip->len);
00806         
00807         he.h_addrtype=ip->af;
00808         he.h_length=ip->len;
00809         he.h_addr_list=p_addr;
00810         he.h_aliases=p_aliases;
00811         he.h_name=hostname;
00812         return &he;
00813 }
00814 
00815 
00816 
00817 /* init a dest_info structure */
00818 #define init_dest_info(dst) \
00819         do{ \
00820                 memset((dst), 0, sizeof(struct dest_info)); \
00821         } while(0) 
00822 
00823 
00824 
00825 /* init a dest_info structure from a recv_info structure */
00826 inline static void init_dst_from_rcv(struct dest_info* dst,
00827                                                                         struct receive_info* rcv)
00828 {
00829                 dst->send_sock=rcv->bind_address;
00830                 dst->to=rcv->src_su;
00831                 dst->id=rcv->proto_reserved1;
00832                 dst->proto=rcv->proto;
00833                 dst->send_flags.f=0;
00834                 dst->send_flags.blst_imask=0;
00835 #ifdef USE_COMP
00836                 dst->comp=rcv->comp;
00837 #endif
00838 }
00839 
00844 int ip_addr_match_net(ip_addr_t *iaddr, ip_addr_t *naddr, int mask);
00845 
00846 #endif

Generated on Tue May 22 2012 13:10:07 for SIP Router by  doxygen 1.7.1