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