82e66123b4a3d57e461789acd6fcc4f70a72df59
[sip-router] / src / core / socket_info.c
1
2 /* 
3  * find & manage listen addresses 
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 /*!
25  * \file
26  * \brief Kamailio core :: find & manage listen addresses 
27  *
28  * This file contains code that initializes and handles Kamailio listen addresses
29  * lists (struct socket_info). It is used mainly on startup.
30  * \ingroup core
31  * Module: \ref core
32  */
33
34 #include <string.h>
35 #include <errno.h>
36 #include <unistd.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/utsname.h>
40 #include <stdio.h>
41
42 #include <sys/ioctl.h>
43 #include <net/if.h>
44 #include <ifaddrs.h>
45 #include <netdb.h>
46 #ifdef HAVE_SYS_SOCKIO_H
47 #include <sys/sockio.h>
48 #endif
49
50 #include "globals.h"
51 #include "socket_info.h"
52 #include "dprint.h"
53 #include "mem/mem.h"
54 #include "ut.h"
55 #include "resolve.h"
56 #include "name_alias.h"
57
58
59
60 /* list manip. functions (internal use only) */
61
62
63 /* append */
64 #define sock_listadd(head, el) \
65         do{\
66                 if (*(head)==0) *(head)=(el); \
67                 else{ \
68                         for((el)->next=*(head); (el)->next->next;\
69                                         (el)->next=(el)->next->next); \
70                         (el)->next->next=(el); \
71                         (el)->prev=(el)->next; \
72                         (el)->next=0; \
73                 }\
74         }while(0)
75
76
77 /* insert after "after" */
78 #define sock_listins(el, after) \
79         do{ \
80                 if ((after)){\
81                         (el)->next=(after)->next; \
82                         if ((after)->next) (after)->next->prev=(el); \
83                         (after)->next=(el); \
84                         (el)->prev=(after); \
85                 }else{ /* after==0 = list head */ \
86                         (after)=(el); \
87                         (el)->next=(el)->prev=0; \
88                 }\
89         }while(0)
90
91
92 #define sock_listrm(head, el) \
93         do {\
94                 if (*(head)==(el)) *(head)=(el)->next; \
95                 if ((el)->next) (el)->next->prev=(el)->prev; \
96                 if ((el)->prev) (el)->prev->next=(el)->next; \
97         }while(0)
98
99
100 #define addr_info_listadd sock_listadd
101 #define addr_info_listins sock_listins
102 #define addr_info_listrm sock_listrm
103
104 /**
105  * return the scope for IPv6 interface matching the ipval parameter
106  * - needed for binding to link local IPv6 addresses
107  */
108 unsigned int ipv6_get_netif_scope(char *ipval)
109 {
110         struct ifaddrs *netiflist = NULL;
111         struct ifaddrs *netif = NULL;
112         char ipaddr[NI_MAXHOST];
113         unsigned int iscope = 0;
114         int i = 0;
115         int r = 0;
116         ip_addr_t *ipa = NULL;
117         ip_addr_t vaddr;
118         str ips;
119
120         ips.s = ipval;
121         ips.len = strlen(ipval);
122
123         ipa = str2ip6(&ips);
124         if(ipa==NULL) {
125                 LM_ERR("could not parse ipv6 address: %s\n", ipval);
126                 return 0;
127         }
128         memcpy(&vaddr, ipa, sizeof(ip_addr_t));
129         ipa = NULL;
130
131         /* walk over the list of all network interface addresses */
132         if(getifaddrs(&netiflist)!=0) {
133                 LM_ERR("failed to get network interfaces - errno: %d\n", errno);
134                 return 0;
135         }
136         for(netif = netiflist; netif; netif = netif->ifa_next) {
137                 /* only active and ipv6 */
138                 if (netif->ifa_addr && (netif->ifa_flags & IFF_UP)
139                                         && netif->ifa_addr->sa_family==AF_INET6) {
140                         r = getnameinfo(netif->ifa_addr, sizeof(struct sockaddr_in6),
141                                         ipaddr, sizeof(ipaddr), NULL, 0, NI_NUMERICHOST);
142                         if(r!=0) {
143                                 LM_ERR("failed to get the name info - ret: %d\n", r);
144                                 goto done;
145                         }
146                         /* strip the interface name after */
147                         for(i=0; ipaddr[i]; i++) {
148                                 if(ipaddr[i]=='%') {
149                                         ipaddr[i]='\0';
150                                         break;
151                                 }
152                         }
153                         ips.s = ipaddr;
154                         ips.len = strlen(ipaddr);
155                         ipa = str2ip6(&ips);
156                         if(ipa!=NULL) {
157                                 /* if the ips match, get scope index from interface name */
158                                 if(ip_addr_cmp(&vaddr, ipa)) {
159                                         iscope=if_nametoindex(netif->ifa_name);
160                                         goto done;
161                                 }
162                         }
163                 }
164         }
165
166 done:
167         freeifaddrs(netiflist);
168         return iscope;
169 }
170
171 inline static void addr_info_list_ins_lst(struct addr_info* lst,
172                                                                                 struct addr_info* after)
173 {
174         struct addr_info* l;
175         struct addr_info* n;
176         
177         if (lst){
178                 n=after->next;
179                 after->next=lst;
180                 lst->prev=after;
181                 if (n){
182                         for(l=lst; l->next; l=l->next);
183                         l->next=n;
184                         n->prev=l;
185                 }
186         }
187 }
188
189
190 /* protocol order, filled by init_proto_order() */
191 enum sip_protos nxt_proto[PROTO_LAST+1]=
192 { PROTO_UDP, PROTO_TCP, PROTO_TLS, PROTO_SCTP, 0 };
193 /* Deliberately left PROTO_WS and PROTO_WSS out of this as they are just
194    upgraded TCP and TLS connections */
195
196
197
198 /* another helper function, it just fills a struct addr_info
199  * returns: 0 on success, -1 on error*/
200 static int init_addr_info(struct addr_info* a,
201                                                                 char* name, enum si_flags flags)
202 {
203
204         memset(a, 0, sizeof(*a));
205         a->name.len=strlen(name);
206         a->name.s=pkg_malloc(a->name.len+1); /* include \0 */
207         if (a->name.s==0) goto error;
208         memcpy(a->name.s, name, a->name.len+1);
209         a->flags=flags;
210         return 0;
211 error:
212         PKG_MEM_ERROR;
213         return -1;
214 }
215
216
217
218 /* returns 0 on error, new addr_info_lst element on success */
219 static inline struct addr_info* new_addr_info(char* name, 
220                                                                                                         enum si_flags gf)
221 {
222         struct addr_info* al;
223         
224         al=pkg_malloc(sizeof(*al));
225         if (al==0) goto error;
226         al->next=0;
227         al->prev=0;
228         if (init_addr_info(al, name, gf)!=0) goto error;
229         return al;
230 error:
231         PKG_MEM_ERROR;
232         if (al){
233                 if (al->name.s) pkg_free(al->name.s);
234                 pkg_free(al);
235         }
236         return 0;
237 }
238
239
240
241 static inline void free_addr_info(struct addr_info* a)
242 {
243         if (a){
244                 if (a->name.s){
245                         pkg_free(a->name.s);
246                         a->name.s=0;
247                 }
248                 pkg_free(a);
249         }
250 }
251
252
253
254 static inline void free_addr_info_lst(struct addr_info** lst)
255 {
256         struct addr_info* a;
257         struct addr_info* tmp;
258         
259         a=*lst;
260         while(a){
261                 tmp=a;
262                 a=a->next;
263                 free_addr_info(tmp);
264         }
265 }
266
267
268
269 /* adds a new add_info_lst element to the corresponding list
270  * returns 0 on success, -1 on error */
271 static int new_addr_info2list(char* name, enum si_flags f,
272                                                                 struct addr_info** l)
273 {
274         struct addr_info * al;
275         
276         al=new_addr_info(name, f);
277         if (al==0) goto error;
278         addr_info_listadd(l, al);
279         return 0;
280 error:
281         return -1;
282 }
283
284
285
286 /* another helper function, it just creates a socket_info struct
287  * allocates a si and a si->name in new pkg memory */
288 static inline struct socket_info* new_sock_info(        char* name,
289                                                                 struct name_lst* addr_l,
290                                                                 unsigned short port, unsigned short proto,
291                                                                 char *usename, unsigned short useport,
292                                                                 char *sockname, enum si_flags flags)
293 {
294         struct socket_info* si;
295         struct name_lst* n;
296         struct hostent* he;
297         char *p;
298
299         si=(struct socket_info*) pkg_malloc(sizeof(struct socket_info));
300         if (si==0) goto error;
301         memset(si, 0, sizeof(struct socket_info));
302         si->socket=-1;
303         si->name.len=strlen(name);
304         si->name.s=(char*)pkg_malloc(si->name.len+1); /* include \0 */
305         if (si->name.s==0) goto error;
306         memcpy(si->name.s, name, si->name.len+1);
307         /* set port & proto */
308         si->port_no=port;
309         si->proto=proto;
310         si->flags=flags;
311         si->addr_info_lst=0;
312         for (n=addr_l; n; n=n->next){
313                 if (new_addr_info2list(n->name, n->flags, &si->addr_info_lst)!=0){
314                         LM_ERR("new_addr_info2list failed\n");
315                         goto error;
316                 }
317         }
318         if(sockname!=NULL) {
319                 si->sockname.len = strlen(sockname);
320                 si->sockname.s=(char*)pkg_malloc(si->sockname.len+1); /* include \0 */
321                 if (si->sockname.s==0) { goto error; }
322                 memcpy(si->sockname.s, sockname, si->sockname.len+1);
323         }
324         if(usename!=NULL)
325         {
326                 si->useinfo.name.len=strlen(usename);
327                 si->useinfo.name.s=(char*)pkg_malloc(si->useinfo.name.len+1);
328                 if (si->useinfo.name.s==0)
329                         goto error;
330                 strcpy(si->useinfo.name.s, usename);
331                 if(usename[0]=='[' && usename[si->useinfo.name.len-1]==']')
332                 {
333                         si->useinfo.address_str.len = si->useinfo.name.len - 2;
334                         p = si->useinfo.name.s + 1;
335                 } else {
336                         si->useinfo.address_str.len = si->useinfo.name.len;
337                         p = si->useinfo.name.s;
338                 }
339                 si->useinfo.address_str.s=(char*)pkg_malloc(si->useinfo.address_str.len+1);
340                 if(si->useinfo.address_str.s==NULL)
341                         goto error;
342                 strncpy(si->useinfo.address_str.s, p, si->useinfo.address_str.len);
343                 si->useinfo.address_str.s[si->useinfo.address_str.len] = '\0';
344
345                 p = int2str(useport, &si->useinfo.port_no_str.len);
346                 if(p==NULL)
347                         goto error;
348                 si->useinfo.port_no_str.s=(char*)pkg_malloc(si->useinfo.port_no_str.len+1);
349                 if(si->useinfo.port_no_str.s==NULL)
350                         goto error;
351                 strcpy(si->useinfo.port_no_str.s, p);
352                 si->useinfo.port_no = useport;
353
354                 he=resolvehost(si->useinfo.name.s);
355                 if (he==0){
356                         LM_ERR("unable to resolve advertised name %s\n", si->useinfo.name.s);
357                         goto error;
358                 }
359                 hostent2ip_addr(&si->useinfo.address, he, 0);
360         }
361         return si;
362 error:
363         PKG_MEM_ERROR;
364         if (si) {
365                 if(si->name.s) {
366                         pkg_free(si->name.s);
367                 }
368                 if(si->sockname.s) {
369                         pkg_free(si->sockname.s);
370                 }
371                 pkg_free(si);
372         }
373         return 0;
374 }
375
376
377
378 /*  delete a socket_info struct */
379 static void free_sock_info(struct socket_info* si)
380 {
381         if(si){
382                 if(si->name.s) pkg_free(si->name.s);
383                 if(si->address_str.s) pkg_free(si->address_str.s);
384                 if(si->port_no_str.s) pkg_free(si->port_no_str.s);
385                 if(si->addr_info_lst) free_addr_info_lst(&si->addr_info_lst);
386                 if(si->sock_str.s) pkg_free(si->sock_str.s);
387                 if(si->sockname.s) pkg_free(si->sockname.s);
388                 if(si->useinfo.name.s) pkg_free(si->useinfo.name.s);
389                 if(si->useinfo.port_no_str.s) pkg_free(si->useinfo.port_no_str.s);
390                 if(si->useinfo.sock_str.s) pkg_free(si->useinfo.sock_str.s);
391         }
392 }
393
394
395
396 char* get_valid_proto_name(unsigned short proto)
397 {
398         switch(proto){
399                 case PROTO_NONE:
400                         return "*";
401                 case PROTO_UDP:
402                         return "udp";
403 #ifdef USE_TCP
404                 case PROTO_TCP:
405                         return "tcp";
406 #endif
407 #ifdef USE_TLS
408                 case PROTO_TLS:
409                         return "tls";
410 #endif
411 #ifdef USE_SCTP
412                 case PROTO_SCTP:
413                         return "sctp";
414 #endif
415                 default:
416                         return "unknown";
417         }
418 }
419
420 /** Convert socket to its textual representation.
421  *
422  * This function converts the transport protocol, the IP address and the port
423  * number in a comma delimited string of form proto:ip:port. The resulting
424  * string is NOT zero terminated
425  *
426  * @param s is a pointer to the destination memory buffer
427  * @param len is a pointer to an integer variable. Initially the variable
428  *        should contain the size of the buffer in s. The value of the variable
429  *        will be changed to the length of the resulting string on success and
430  *        to the desired size of the destination buffer if it is too small
431  * @param si is a pointer to the socket_info structure to be printed
432  * @return -1 on error and 0 on success
433  */
434 int socket2str(char* s, int* len, struct socket_info* si)
435 {
436         return socketinfo2str(s, len, si, 0);
437 }
438
439 int socketinfo2str(char* s, int* len, struct socket_info* si, int mode)
440 {
441         str proto;
442         int l;
443         
444         proto.s = get_valid_proto_name(si->proto);
445         proto.len = strlen(proto.s);
446         
447         if(mode==1)
448                 l = proto.len + si->useinfo.name.len + si->useinfo.port_no_str.len + 2;
449         else
450                 l = proto.len + si->address_str.len + si->port_no_str.len + 2;
451
452         if(si->address.af==AF_INET6)
453                 l += 2;
454         
455         if (*len < l) {
456                 LM_ERR("Destionation buffer too short\n");
457                 *len = l;
458                 return -1;
459         }
460         
461         memcpy(s, proto.s, proto.len);
462         s += proto.len;
463         *s = ':'; s++;
464         if(mode==1){
465                 memcpy(s, si->useinfo.name.s, si->useinfo.name.len);
466                 s += si->useinfo.name.len;
467                 *s = ':'; s++;
468                 memcpy(s, si->useinfo.port_no_str.s, si->useinfo.port_no_str.len);
469                 s += si->useinfo.port_no_str.len;
470         } else {
471                 if(si->address.af==AF_INET6) {
472                         *s = '['; s++;
473                 }
474                 memcpy(s, si->address_str.s, si->address_str.len);
475                 s += si->address_str.len;
476                 if(si->address.af==AF_INET6) {
477                         *s = ']'; s++;
478                 }
479                 *s = ':'; s++;
480                 memcpy(s, si->port_no_str.s, si->port_no_str.len);
481                 s += si->port_no_str.len;
482         }
483
484         *len = l;
485         return 0;
486 }
487
488
489
490 /* Fill si->sock_str with string representing the socket_info structure,
491  * format of the string is 'proto:address:port'. Returns 0 on success and
492  * negative number on failure.
493  */
494 static int fix_sock_str(struct socket_info* si)
495 {
496         int len = MAX_SOCKET_STR;
497
498         if (si->sock_str.s) pkg_free(si->sock_str.s);
499         
500         si->sock_str.s = pkg_malloc(len + 1);
501         if (si->sock_str.s == NULL) {
502                 PKG_MEM_ERROR;
503                 return -1;
504         }
505         if (socketinfo2str(si->sock_str.s, &len, si, 0) < 0) {
506                 BUG("fix_sock_str: Error in socket to str\n");
507                 return -1;
508         }
509         si->sock_str.s[len] = '\0';
510         si->sock_str.len = len;
511         if(si->useinfo.name.s!=NULL)
512         {
513                 len = MAX_SOCKET_ADVERTISE_STR;
514
515                 if (si->useinfo.sock_str.s) pkg_free(si->useinfo.sock_str.s);
516
517                 si->useinfo.sock_str.s = pkg_malloc(len + 1);
518                 if (si->useinfo.sock_str.s == NULL) {
519                         PKG_MEM_ERROR;
520                         return -1;
521                 }
522                 if (socketinfo2str(si->useinfo.sock_str.s, &len, si, 1) < 0) {
523                         BUG("fix_sock_str: Error in socket to str\n");
524                         return -1;
525                 }
526                 si->useinfo.sock_str.s[len] = '\0';
527                 si->useinfo.sock_str.len = len;
528         }
529         return 0;
530 }
531
532
533 /* returns 0 if support for the protocol is not compiled or if proto is 
534    invalid */
535 struct socket_info** get_sock_info_list(unsigned short proto)
536 {
537         
538         switch(proto){
539                 case PROTO_UDP:
540                         return &udp_listen;
541                         break;
542                 case PROTO_TCP:
543                 case PROTO_WS:
544 #ifdef USE_TCP
545                         return &tcp_listen;
546 #endif
547                         break;
548                 case PROTO_TLS:
549                 case PROTO_WSS:
550 #ifdef USE_TLS
551                         return &tls_listen;
552 #endif
553                         break;
554                 case PROTO_SCTP:
555 #ifdef USE_SCTP
556                         return &sctp_listen;
557 #endif
558                         break;
559                 default:
560                         LM_CRIT("invalid proto %d\n", proto);
561         }
562         return 0;
563 }
564
565
566 /* helper function for grep_sock_info
567  * params:
568  *  host - hostname to compare with
569  *  name - official name
570  *  addr_str - name's resolved ip address converted to string
571  *  ip_addr - name's ip address 
572  *  flags - set to SI_IS_IP if name contains an IP
573  *
574  * returns 0 if host matches, -1 if not */
575 inline static int si_hname_cmp(str* host, str* name, str* addr_str, 
576                                                                 struct ip_addr* ip_addr, int flags)
577 {
578         struct ip_addr* ip6;
579         
580         if ( (host->len==name->len) && 
581                 (strncasecmp(host->s, name->s, name->len)==0) /*slower*/)
582                 /* comp. must be case insensitive, host names
583                  * can be written in mixed case, it will also match
584                  * ipv6 addresses if we are lucky*/
585                 goto found;
586         /* check if host == ip address */
587         /* ipv6 case is uglier, host can be [3ffe::1] */
588         ip6=str2ip6(host);
589         if (ip6){
590                 if (ip_addr_cmp(ip6, ip_addr))
591                         goto found; /* match */
592                 else
593                         return -1; /* no match, but this is an ipv6 address
594                                                  so no point in trying ipv4 */
595         }
596         /* ipv4 */
597         if ( (!(flags&SI_IS_IP)) && (host->len==addr_str->len) && 
598                         (memcmp(host->s, addr_str->s, addr_str->len)==0) )
599                 goto found;
600         return -1;
601 found:
602         return 0;
603 }
604
605
606 /* checks if the proto: host:port is one of the address we listen on
607  * and returns the corresponding socket_info structure.
608  * if port==0, the  port number is ignored
609  * if proto==0 (PROTO_NONE) the protocol is ignored
610  * returns  0 if not found
611  * WARNING: uses str2ip6 so it will overwrite any previous
612  *  unsaved result of this function (static buffer)
613  */
614 struct socket_info* grep_sock_info(str* host, unsigned short port,
615                                                                                                 unsigned short proto)
616 {
617         str hname;
618         struct socket_info* si;
619         struct socket_info** list;
620         struct addr_info* ai;
621         unsigned short c_proto;
622         
623         hname=*host;
624         if ((hname.len>2)&&((*hname.s)=='[')&&(hname.s[hname.len-1]==']')){
625                 /* ipv6 reference, skip [] */
626                 hname.s++;
627                 hname.len-=2;
628         }
629
630         c_proto=(proto!=PROTO_NONE)?proto:PROTO_UDP;
631 retry:
632         do{
633                 /* get the proper sock_list */
634                 list=get_sock_info_list(c_proto);
635         
636                 if (list==0) /* disabled or unknown protocol */
637                         continue;
638                 for (si=*list; si; si=si->next){
639                         LM_DBG("checking if host==us: %d==%d && [%.*s] == [%.*s]\n",
640                                                 hname.len,
641                                                 si->name.len,
642                                                 hname.len, hname.s,
643                                                 si->name.len, si->name.s
644                                 );
645                         if (port) {
646                                 LM_DBG("checking if port %d (advertise %d) matches port %d\n",
647                                                 si->port_no, si->useinfo.port_no, port);
648                                 if (si->port_no!=port && si->useinfo.port_no!=port) {
649                                         continue;
650                                 }
651                         }
652                         if (si_hname_cmp(&hname, &si->name, &si->address_str, 
653                                                                 &si->address, si->flags)==0)
654                                 goto found;
655                         if(si->useinfo.name.s!=NULL)
656                         {
657                                 LM_DBG("checking advertise if host==us:"
658                                                 " %d==%d && [%.*s] == [%.*s]\n",
659                                                 hname.len,
660                                                 si->useinfo.name.len,
661                                                 hname.len, hname.s,
662                                                 si->useinfo.name.len, si->useinfo.name.s
663                                 );
664                                 if (si_hname_cmp(&hname, &si->useinfo.name,
665                                                         &si->useinfo.address_str, &si->useinfo.address,
666                                                         si->flags)==0)
667                                         goto found;
668                         }
669                         /* try among the extra addresses */
670                         for (ai=si->addr_info_lst; ai; ai=ai->next)
671                                 if (si_hname_cmp(&hname, &ai->name, &ai->address_str, 
672                                                                         &ai->address, ai->flags)==0)
673                                         goto found;
674                 }
675
676         }while( (proto==0) && (c_proto=next_proto(c_proto)) );
677
678 #ifdef USE_TLS
679         if (unlikely(c_proto == PROTO_WS)) {
680                 c_proto = PROTO_WSS;
681                 goto retry;
682         }
683 #endif
684 /* not_found: */
685         return 0;
686 found:
687         return si;
688 }
689
690 /* checks if the proto:port is one of the ports we listen on
691  * and returns the corresponding socket_info structure.
692  * if proto==0 (PROTO_NONE) the protocol is ignored
693  * returns  0 if not found
694  */
695 struct socket_info* grep_sock_info_by_port(unsigned short port, 
696                                                                                         unsigned short proto)
697 {
698         struct socket_info* si;
699         struct socket_info** list;
700         unsigned short c_proto;
701
702         if (!port) {
703                 goto not_found;
704         }
705         c_proto=(proto!=PROTO_NONE)?proto:PROTO_UDP;
706         do{
707                 /* get the proper sock_list */
708                 list=get_sock_info_list(c_proto);
709         
710                 if (list==0) /* disabled or unknown protocol */
711                         continue;
712                 
713                 for (si=*list; si; si=si->next){
714                         LM_DBG("checking if port %d matches port %d\n", si->port_no, port);
715                         if (si->port_no==port) {
716                                 goto found;
717                         }
718                 }
719         }while( (proto==0) && (c_proto=next_proto(c_proto)) );
720 not_found:
721         return 0;
722 found:
723         return si;
724 }
725
726
727
728 /* checks if the proto: ip:port is one of the address we listen on
729  * and returns the corresponding socket_info structure.
730  * (same as grep_socket_info, but use ip addr instead)
731  * if port==0, the  port number is ignored
732  * if proto==0 (PROTO_NONE) the protocol is ignored
733  * returns  0 if not found
734  * WARNING: uses str2ip6 so it will overwrite any previous
735  *  unsaved result of this function (static buffer)
736  */
737 struct socket_info* find_si(struct ip_addr* ip, unsigned short port,
738                                                                                                 unsigned short proto)
739 {
740         struct socket_info* si;
741         struct socket_info** list;
742         struct addr_info* ai;
743         unsigned short c_proto;
744         
745         c_proto=(proto!=PROTO_NONE)?proto:PROTO_UDP;
746         do{
747                 /* get the proper sock_list */
748                 list=get_sock_info_list(c_proto);
749         
750                 if (list==0) /* disabled or unknown protocol */
751                         continue;
752                 
753                 for (si=*list; si; si=si->next){
754                         if (port) {
755                                 if (si->port_no!=port) {
756                                         continue;
757                                 }
758                         }
759                         if (ip_addr_cmp(ip, &si->address)
760                                         || ip_addr_cmp(ip, &si->useinfo.address))
761                                 goto found;
762                         for (ai=si->addr_info_lst; ai; ai=ai->next)
763                                 if (ip_addr_cmp(ip, &ai->address))
764                                         goto found;
765                 }
766         }while( (proto==0) && (c_proto=next_proto(c_proto)) );
767 /* not_found: */
768         return 0;
769 found:
770         return si;
771 }
772
773
774
775 /* append a new sock_info structure to the corresponding list
776  * return  new sock info on success, 0 on error */
777 static struct socket_info* new_sock2list(char* name, struct name_lst* addr_l,
778                                                                         unsigned short port,
779                                                                         unsigned short proto,
780                                                                         char *usename, unsigned short useport,
781                                                                         char *sockname,
782                                                                         enum si_flags flags,
783                                                                         struct socket_info** list)
784 {
785         struct socket_info* si;
786         /* allocates si and si->name in new pkg memory */
787         si=new_sock_info(name, addr_l, port, proto, usename, useport, sockname, flags);
788         if (si==0){
789                 LM_ERR("new_sock_info failed\n");
790                 goto error;
791         }
792         if(socket_workers>0) {
793                 si->workers = socket_workers;
794                 socket_workers = 0;
795         }
796 #ifdef USE_MCAST
797         if (mcast!=0) {
798                 si->mcast.len=strlen(mcast);
799                 si->mcast.s=(char*)pkg_malloc(si->mcast.len+1);
800                 if (si->mcast.s==0) {
801                         PKG_MEM_ERROR;
802                         pkg_free(si->name.s);
803                         pkg_free(si);
804                         return 0;
805                 }
806                 strcpy(si->mcast.s, mcast);
807                 mcast = 0;
808         }
809 #endif /* USE_MCAST */
810         sock_listadd(list, si);
811         return si;
812 error:
813         return 0;
814 }
815
816
817
818 /* adds a new sock_info structure immediately after "after"
819  * return  new sock info on success, 0 on error */
820 static struct socket_info* new_sock2list_after(char* name,
821                                                                         struct name_lst* addr_l,
822                                                                         unsigned short port,
823                                                                         unsigned short proto,
824                                                                         char *usename,
825                                                                         unsigned short useport,
826                                                                         char *sockname,
827                                                                         enum si_flags flags,
828                                                                         struct socket_info* after)
829 {
830         struct socket_info* si;
831
832         si=new_sock_info(name, addr_l, port, proto, usename, useport, sockname, flags);
833         if (si==0){
834                 LM_ERR("new_sock_info failed\n");
835                 goto error;
836         }
837         sock_listins(si, after);
838         return si;
839 error:
840         return 0;
841 }
842
843
844
845 /* adds a sock_info structure to the corresponding proto list
846  * return  0 on success, -1 on error */
847 int add_listen_advertise_iface_name(char* name, struct name_lst* addr_l,
848                                                 unsigned short port, unsigned short proto,
849                                                 char *usename, unsigned short useport, char *sockname,
850                                                 enum si_flags flags)
851 {
852         struct socket_info** list;
853         unsigned short c_proto;
854         struct name_lst* a_l;
855         unsigned short c_port;
856
857         c_proto=(proto!=PROTO_NONE)?proto:PROTO_UDP;
858         do{
859                 list=get_sock_info_list(c_proto);
860                 if (list==0) /* disabled or unknown protocol */
861                         continue;
862
863                 if (port==0){ /* use default port */
864                         c_port=
865 #ifdef USE_TLS
866                                 ((c_proto)==PROTO_TLS)?tls_port_no:
867 #endif
868                                 port_no;
869                 }
870 #ifdef USE_TLS
871                 else if ((c_proto==PROTO_TLS) && (proto==0)){
872                         /* -l  ip:port => on udp:ip:port; tcp:ip:port and tls:ip:port+1?*/
873                         c_port=port+1;
874                 }
875 #endif
876                 else{
877                         c_port=port;
878                 }
879                 if (c_proto!=PROTO_SCTP){
880                         if (new_sock2list(name, 0, c_port, c_proto, usename, useport,
881                                                                 sockname, flags & ~SI_IS_MHOMED, list)==0){
882                                 LM_ERR("new_sock2list failed\n");
883                                 goto error;
884                         }
885                         /* add the other addresses in the list as separate sockets
886                          * since only SCTP can bind to multiple addresses */
887                         for (a_l=addr_l; a_l; a_l=a_l->next){
888                                 if (new_sock2list(a_l->name, 0, c_port,
889                                                                         c_proto, usename, useport, sockname,
890                                                                         flags & ~SI_IS_MHOMED, list)==0){
891                                         LM_ERR("new_sock2list failed\n");
892                                         goto error;
893                                 }
894                         }
895                 }else{
896                         if (new_sock2list(name, addr_l, c_port, c_proto, usename, useport,
897                                                 sockname, flags, list)==0){
898                                 LM_ERR("new_sock2list failed\n");
899                                 goto error;
900                         }
901                 }
902         }while( (proto==0) && (c_proto=next_proto(c_proto)));
903         return 0;
904 error:
905         return -1;
906 }
907
908 /* adds a sock_info structure to the corresponding proto list
909  * return  0 on success, -1 on error */
910 int add_listen_advertise_iface(char* name, struct name_lst* addr_l,
911                                                 unsigned short port, unsigned short proto,
912                                                 char *usename, unsigned short useport,
913                                                 enum si_flags flags)
914 {
915         return add_listen_advertise_iface_name(name, addr_l, port, proto,
916                                                 usename, useport, NULL, flags);
917 }
918
919 /* adds a sock_info structure to the corresponding proto list
920  * return  0 on success, -1 on error */
921 int add_listen_iface(char* name, struct name_lst* addr_l,
922                                                 unsigned short port, unsigned short proto,
923                                                 enum si_flags flags)
924 {
925         return add_listen_advertise_iface_name(name, addr_l, port, proto, 0, 0, 0,
926                         flags);
927 }
928
929 /* adds a sock_info structure to the corresponding proto list
930  * return  0 on success, -1 on error */
931 int add_listen_iface_name(char* name, struct name_lst* addr_l,
932                                                 unsigned short port, unsigned short proto, char *sockname,
933                                                 enum si_flags flags)
934 {
935         return add_listen_advertise_iface_name(name, addr_l, port, proto, 0, 0,
936                         sockname, flags);
937 }
938
939 #ifdef __OS_linux
940
941 #include "linux/types.h"
942 #include "linux/netlink.h"
943 #include "linux/rtnetlink.h"
944 #include "arpa/inet.h"
945
946
947 #define MAX_IF_LEN 64
948 struct idx
949 {
950         struct idx *    next;
951         int             family;
952         unsigned        ifa_flags;
953         char            addr[MAX_IF_LEN];
954
955 };
956
957 struct idxlist{
958         struct idx*     addresses;
959         int             index;
960         char            name[MAX_IF_LEN];
961         unsigned        flags;
962 };
963
964 #define MAX_IFACE_NO 32
965
966 static struct idxlist *ifaces = NULL;
967 static int seq = 0;
968
969 #define SADDR(s) ((struct sockaddr_in*)s)->sin_addr.s_addr
970
971 #define NLMSG_TAIL(nmsg) \
972         ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
973
974 int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
975               int alen)
976 {
977         int len = RTA_LENGTH(alen);
978         struct rtattr *rta;
979
980         if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
981                 fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",maxlen);
982                 return -1;
983         }
984         rta = NLMSG_TAIL(n);
985         rta->rta_type = type;
986         rta->rta_len = len;
987         memcpy(RTA_DATA(rta), data, alen);
988         n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
989         return 0;
990 }
991
992
993
994 static int nl_bound_sock(void)
995 {
996         int sock = -1;
997         struct sockaddr_nl la;
998
999         sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
1000         if(sock < 0){
1001                 LM_ERR("could not create NETLINK sock to get interface list\n");
1002                 goto error;
1003         }
1004
1005         /* bind NETLINK socket to pid */
1006         bzero(&la, sizeof(la));
1007         la.nl_family = AF_NETLINK;
1008         la.nl_pad = 0;
1009         la.nl_pid = getpid();
1010         la.nl_groups = 0;
1011         if ( bind(sock, (struct sockaddr*) &la, sizeof(la)) < 0){
1012                 LM_ERR("could not bind NETLINK sock to sockaddr_nl\n");
1013                 goto error;
1014         }
1015
1016         return sock;
1017 error:
1018         if(sock >= 0) close(sock);
1019         return -1;
1020 }
1021
1022 #define fill_nl_req(req, type, family) do {\
1023         memset(&req, 0, sizeof(req));\
1024         req.nlh.nlmsg_len = sizeof(req);\
1025         req.nlh.nlmsg_type = type;\
1026         req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_DUMP;\
1027         req.nlh.nlmsg_pid = getpid();\
1028         req.nlh.nlmsg_seq = seq++;\
1029         req.g.rtgen_family = family;\
1030         } while(0);
1031
1032         
1033 static int get_flags(int family){
1034         struct {
1035                 struct nlmsghdr nlh;
1036                 struct rtgenmsg g;
1037         } req;
1038         int rtn = 0;
1039         struct nlmsghdr*  nlp;
1040         struct ifinfomsg *ifi;
1041         char buf[8192];
1042         char *p = buf;
1043         int nll = 0;
1044     int nl_sock = -1;
1045
1046         fill_nl_req(req, RTM_GETLINK, AF_INET);
1047
1048         if((nl_sock = nl_bound_sock()) < 0) return -1;
1049
1050         if(send(nl_sock, (void*)&req, sizeof(req), 0) < 0)
1051         {
1052                 LM_ERR("error sending NETLINK request\n");
1053                 goto error;
1054         }
1055
1056         while(1) {
1057                 rtn = recv(nl_sock, p, sizeof(buf) - nll, 0);
1058                 nlp = (struct nlmsghdr *) p;
1059                 if(nlp->nlmsg_type == NLMSG_DONE){
1060                         LM_DBG("done\n");
1061                          break;
1062                 }
1063                 if(nlp->nlmsg_type == NLMSG_ERROR){
1064                          LM_DBG("Error on message to netlink");
1065                          break;
1066                 }
1067                 p += rtn;
1068
1069                 nll += rtn;
1070         }
1071
1072         nlp = (struct nlmsghdr *) buf;
1073         for(;NLMSG_OK(nlp, nll);nlp=NLMSG_NEXT(nlp, nll)){
1074                 ifi = NLMSG_DATA(nlp);
1075
1076                 if (nlp->nlmsg_len < NLMSG_LENGTH(sizeof(ifi)))
1077                         goto error;
1078
1079                 LM_ERR("Interface with index %d has flags %d\n", ifi->ifi_index, ifi->ifi_flags);
1080                 if(ifaces == NULL){
1081                         LM_ERR("get_flags must not be called on empty interface list");
1082                         goto error;
1083                 }
1084                 if(ifi->ifi_index >= MAX_IFACE_NO){
1085                         LM_ERR("invalid network interface index returned %d", ifi->ifi_index);
1086                         goto error;
1087                 }
1088                 ifaces[ifi->ifi_index].flags = ifi->ifi_flags;
1089         }
1090
1091         if(nl_sock>=0) close(nl_sock);
1092         return 0;
1093
1094 error:
1095         if(nl_sock>=0) close(nl_sock);
1096         return -1;
1097 }
1098
1099 static int build_iface_list(void)
1100 {
1101         struct {
1102                 struct nlmsghdr nlh;
1103                 struct rtgenmsg g;
1104         } req;
1105
1106         int rtn = 0;
1107         struct nlmsghdr*  nlp;
1108         struct ifaddrmsg *ifi;
1109         int rtl;
1110         char buf[8192];
1111         char *p = buf;
1112         int nll = 0;
1113         struct rtattr * rtap;
1114         int index, i;
1115         struct idx* entry;
1116         struct idx* tmp;
1117         int nl_sock = -1;
1118         int families[] = {AF_INET, AF_INET6};
1119         char name[MAX_IF_LEN];
1120         int is_link_local = 0;
1121
1122         if(ifaces == NULL){
1123                 if((ifaces = (struct idxlist*)pkg_malloc(MAX_IFACE_NO
1124                                                 *sizeof(struct idxlist))) == NULL){
1125                         PKG_MEM_ERROR;
1126                         return -1;
1127                 }
1128                 memset(ifaces, 0, sizeof(struct idxlist)*MAX_IFACE_NO);
1129         }
1130
1131         /* bind netlink socket */
1132         if((nl_sock = nl_bound_sock()) < 0) return -1;
1133
1134         for (i = 0 ; i < sizeof(families)/sizeof(int); i++) {
1135                 fill_nl_req(req, RTM_GETADDR, families[i]);
1136
1137                 if(send(nl_sock, (void*)&req, sizeof(req), 0) < 0){
1138                         LM_ERR("error sending NETLINK request\n");
1139                         goto error;
1140                 };
1141
1142                 memset(buf, 0, sizeof(buf));
1143                 nll = 0;
1144                 p = buf;
1145                 while(1) {
1146                         rtn = recv(nl_sock, p, sizeof(buf) - nll, 0);
1147                         LM_DBG("received %d byles \n", rtn);
1148                         nlp = (struct nlmsghdr *) p;
1149                         if(nlp->nlmsg_type == NLMSG_DONE){
1150                                 LM_DBG("done receiving netlink info \n");
1151                                  break;
1152                         }
1153                         if(nlp->nlmsg_type == NLMSG_ERROR){
1154                                  LM_ERR("Error on message to netlink");
1155                                  break;
1156                         }
1157                         p += rtn;
1158
1159                         nll += rtn;
1160                 }
1161
1162                 nlp = (struct nlmsghdr *) buf;
1163                 for(;NLMSG_OK(nlp, nll);nlp=NLMSG_NEXT(nlp, nll)){
1164                         ifi = NLMSG_DATA(nlp);
1165
1166                         if (nlp->nlmsg_len < NLMSG_LENGTH(sizeof(ifi)))
1167                                 continue;
1168                         // init all the strings
1169                         // inner loop: loop thru all the attributes of
1170                         // one route entry
1171                         rtap = (struct rtattr *) IFA_RTA(ifi);
1172
1173                         rtl = IFA_PAYLOAD(nlp);
1174
1175                         index = ifi->ifa_index;
1176                         if(index >= MAX_IFACE_NO){
1177                                 LM_ERR("Invalid interface index returned: %d\n", index);
1178                                 goto error;
1179                         }
1180
1181                         entry = (struct idx*)pkg_malloc(sizeof(struct idx));
1182                         if(entry == 0)
1183                         {
1184                                 PKG_MEM_ERROR;
1185                                 goto error;
1186                         }
1187
1188                         entry->next = 0;
1189                         entry->family = families[i];
1190                         entry->ifa_flags = ifi->ifa_flags;
1191             is_link_local = 0;
1192
1193                         name[0] = '\0';
1194                         for(;RTA_OK(rtap, rtl);rtap=RTA_NEXT(rtap,rtl)){
1195                                 switch(rtap->rta_type){
1196                                         case IFA_ADDRESS:
1197                                                 if((*(int*)RTA_DATA(rtap))== htons(0xfe80)){
1198                                                         LM_DBG("Link Local Address, ignoring ...\n");
1199                                                         is_link_local = 1;
1200                                                         break;
1201                                                 }
1202                                                 inet_ntop(families[i], RTA_DATA(rtap), entry->addr, MAX_IF_LEN);
1203                                                 LM_DBG("iface <IFA_ADDRESS> addr is  %s\n", entry->addr);
1204                                                 break;
1205                                         case IFA_LOCAL:
1206                                                 if((*(int*)RTA_DATA(rtap))== htons(0xfe80)){
1207                                                         LM_DBG("Link Local Address, ignoring ...\n");
1208                                                         is_link_local = 1;
1209                                                 }
1210                                                 inet_ntop(families[i], RTA_DATA(rtap), entry->addr, MAX_IF_LEN);
1211                                                 LM_DBG("iface <IFA_LOCAL> addr is %s\n", entry->addr);
1212                                                 break;
1213                                         case IFA_LABEL:
1214                                                 LM_DBG("iface name is %s\n", (char*)RTA_DATA(rtap));
1215                                                 strncpy(name, (char*)RTA_DATA(rtap), MAX_IF_LEN-1);
1216                                                 break;
1217                                         case IFA_BROADCAST:
1218                                         case IFA_ANYCAST:
1219                                         case IFA_UNSPEC:
1220                                         case IFA_CACHEINFO:
1221                                         default:
1222                                                 break;
1223                                 }
1224                         }
1225                         if(is_link_local) {
1226                                 if(sr_bind_ipv6_link_local==0) {
1227                                         /* skip - link local addresses are not bindable without scope */
1228                                         pkg_free(entry);
1229                                         continue;
1230                                 }
1231                         }
1232
1233                         if(strlen(ifaces[index].name)==0 && strlen(name)>0) {
1234                                 strncpy(ifaces[index].name, name, MAX_IF_LEN-1);
1235                         }
1236
1237                         ifaces[index].index = index;
1238
1239                         if(ifaces[index].addresses == 0 )
1240                                 ifaces[index].addresses = entry;
1241                         else {
1242                                 for(tmp = ifaces[index].addresses; tmp->next ; tmp = tmp->next)/*empty*/;
1243                                 tmp->next = entry;
1244                         }
1245                 }
1246         }
1247         if(nl_sock>0) close(nl_sock);
1248         /* the socket should be closed so we can bind again */
1249         for(i = 0; i < sizeof(families)/sizeof(int); i++){
1250                 /* get device flags */
1251                 get_flags(families[i]); /* AF_INET or AF_INET6 */
1252         }
1253
1254         return 0;
1255 error:
1256         if(nl_sock>=0) close(nl_sock);
1257         return -1;
1258
1259 }
1260 /* add all family type addresses of interface if_name to the socket_info array
1261  * if family ==0, uses all families
1262  * if if_name==0, adds all addresses on all interfaces
1263  * uses RTNETLINK sockets to get addresses on the present interface on LINUX
1264  * return: -1 on error, 0 on success
1265  */
1266 int add_interfaces_via_netlink(char* if_name, int family, unsigned short port,
1267                                         unsigned short proto,
1268                                         struct addr_info** ai_l)
1269 {
1270         int i;
1271         struct idx* tmp;
1272         enum si_flags flags;
1273
1274         if(ifaces == NULL && (build_iface_list()!=0)){
1275                 LM_ERR("Could not get network interface list\n");
1276                 return -1;
1277         }
1278
1279         flags=SI_NONE;
1280         for(i=0; i< MAX_IFACE_NO; ++i){
1281                 if(ifaces[i].addresses == NULL) continue; /* not present/configured */
1282                 if ((if_name==0)||
1283                         (strncmp(if_name, ifaces[i].name, strlen(ifaces[i].name))==0)){
1284
1285                         /* check if iface is up */
1286                         //if(! (ifaces[i].flags & IFF_UP) ) continue;
1287
1288                         for(tmp = ifaces[i].addresses; tmp; tmp = tmp->next){
1289                                 LM_DBG("in add_iface_via_netlink Name %s Address %s\n",
1290                                                         ifaces[i].name, tmp->addr);
1291                                         /* match family */
1292                                         if (family && family == tmp->family){
1293                                         /* check if loopback */
1294                                         if (ifaces[i].flags & IFF_LOOPBACK){
1295                                                 LM_DBG("INTERFACE %s is loopback", ifaces[i].name);
1296                                                 flags|=SI_IS_LO;
1297                                         }
1298                                         /* save the info */
1299                                         if (new_addr_info2list(tmp->addr, flags, ai_l)!=0){
1300                                                 LM_ERR("new_addr_info2list failed\n");
1301                                                 goto error;
1302                                         }
1303                                 }
1304                         }
1305                 }
1306         }
1307         return 0;
1308 error:
1309         return -1;
1310 }
1311 #endif /* __OS_linux */
1312
1313 /* add all family type addresses of interface if_name to the socket_info array
1314  * if family ==0, uses all families
1315  * if if_name==0, adds all addresses on all interfaces
1316  * return: -1 on error, 0 on success
1317  */
1318 int add_interfaces(char* if_name, int family, unsigned short port,
1319                                         unsigned short proto,
1320                                         struct addr_info** ai_l)
1321 {
1322         char* tmp;
1323         struct ip_addr addr;
1324         int ret = -1;
1325         enum si_flags flags;
1326         struct ifaddrs *ifap, *ifa;
1327
1328         if (getifaddrs (&ifap) != 0) {
1329                 LM_ERR("getifaddrs failed\n");
1330                 return -1;
1331         }
1332
1333         for (ifa = ifap; ifa; ifa = ifa->ifa_next)
1334         {
1335                 /* skip if no IP addr associated with the interface */
1336                 if (ifa->ifa_addr==0)
1337                         continue;
1338 #ifdef AF_PACKET
1339                 /* skip AF_PACKET addr family since it is of no use later on */
1340                 if (ifa->ifa_addr->sa_family == AF_PACKET)
1341                         continue;
1342 #endif
1343                 if (if_name && strcmp(if_name, ifa->ifa_name))
1344                         continue;
1345                 if (family && family != ifa->ifa_addr->sa_family)
1346                         continue;
1347                 sockaddr2ip_addr(&addr, (struct sockaddr*)ifa->ifa_addr);
1348                 tmp=ip_addr2a(&addr);
1349                 if (ifa->ifa_flags & IFF_LOOPBACK)
1350                         flags = SI_IS_LO;
1351                 else
1352                         flags = SI_NONE;
1353                 if (new_addr_info2list(tmp, flags, ai_l)!=0)
1354                 {
1355                         LM_ERR("new_addr_info2list failed\n");
1356                         ret = -1;
1357                         break;
1358                 }
1359                 LM_DBG("If: %8s Fam: %8x Flg: %16lx Adr: %s\n",
1360                                 ifa->ifa_name, ifa->ifa_addr->sa_family,
1361                                 (unsigned long)ifa->ifa_flags, tmp);
1362
1363                 ret = 0;
1364         }
1365         freeifaddrs(ifap);
1366         return  ret;
1367 }
1368
1369
1370
1371 /* internal helper function: resolve host names and add aliases
1372  * name is a value result parameter: it should contain the hostname that
1373  * will be used to fill all the other members, including name itself
1374  * in some situation (name->s should be a 0 terminated pkg_malloc'ed string)
1375  * return 0 on success and -1 on error */
1376 static int fix_hostname(str* name, struct ip_addr* address, str* address_str,
1377                                                 enum si_flags* flags, int* type_flags,
1378                                                 struct socket_info* s)
1379 {
1380         struct hostent* he;
1381         char* tmp;
1382         char** h;
1383         
1384         /* get "official hostnames", all the aliases etc. */
1385         he=resolvehost(name->s);
1386         if (he==0){
1387                 LM_ERR("could not resolve %s\n", name->s);
1388                 goto error;
1389         }
1390         /* check if we got the official name */
1391         if (strcasecmp(he->h_name, name->s)!=0){
1392                 if (sr_auto_aliases && 
1393                                 add_alias(name->s, name->len, s->port_no, s->proto)<0){
1394                         LM_ERR("add_alias failed\n");
1395                 }
1396                 /* change the official name */
1397                 pkg_free(name->s);
1398                 name->s=(char*)pkg_malloc(strlen(he->h_name)+1);
1399                 if (name->s==0){
1400                         PKG_MEM_ERROR;
1401                         goto error;
1402                 }
1403                 name->len=strlen(he->h_name);
1404                 strncpy(name->s, he->h_name, name->len+1);
1405         }
1406         /* add the aliases*/
1407         for(h=he->h_aliases; sr_auto_aliases && h && *h; h++)
1408                 if (add_alias(*h, strlen(*h), s->port_no, s->proto)<0){
1409                         LM_ERR("add_alias failed\n");
1410                 }
1411         hostent2ip_addr(address, he, 0); /*convert to ip_addr format*/
1412         if (type_flags){
1413                 *type_flags|=(address->af==AF_INET)?SOCKET_T_IPV4:SOCKET_T_IPV6;
1414         }
1415         if ((tmp=ip_addr2a(address))==0) goto error;
1416         address_str->s=pkg_malloc(strlen(tmp)+1);
1417         if (address_str->s==0){
1418                 PKG_MEM_ERROR;
1419                 goto error;
1420         }
1421         strncpy(address_str->s, tmp, strlen(tmp)+1);
1422         /* set is_ip (1 if name is an ip address, 0 otherwise) */
1423         address_str->len=strlen(tmp);
1424         if (sr_auto_aliases && (address_str->len==name->len) &&
1425                 (strncasecmp(address_str->s, name->s, address_str->len)==0)){
1426                 *flags|=SI_IS_IP;
1427                 /* do rev. DNS on it (for aliases)*/
1428                 he=rev_resolvehost(address);
1429                 if (he==0){
1430                         LM_WARN("could not rev. resolve %s\n", name->s);
1431                 }else{
1432                         /* add the aliases*/
1433                         if (add_alias(he->h_name, strlen(he->h_name), s->port_no,
1434                                                         s->proto)<0){
1435                                 LM_ERR("add_alias failed\n");
1436                         }
1437                         for(h=he->h_aliases; h && *h; h++)
1438                                 if (add_alias(*h, strlen(*h), s->port_no, s->proto) < 0){
1439                                         LM_ERR("add_alias failed\n");
1440                                 }
1441                 }
1442         }
1443         
1444 #ifdef USE_MCAST
1445         /* Check if it is an multicast address and
1446          * set the flag if so
1447          */
1448         if (is_mcast(address)){
1449                 *flags |= SI_IS_MCAST;
1450         }
1451 #endif /* USE_MCAST */
1452         
1453         /* check if INADDR_ANY */
1454         if (ip_addr_any(address))
1455                 *flags|=SI_IS_ANY;
1456         else if (ip_addr_loopback(address)) /* check for loopback */
1457                 *flags|=SI_IS_LO;
1458         
1459         return 0;
1460 error:
1461         return -1;
1462 }
1463
1464
1465
1466 /* append new elements to a socket_info list after "list"
1467  * each element is created  from addr_info_lst + port, protocol and flags
1468  * return 0 on succes, -1 on error
1469  */
1470 static int addr_info_to_si_lst(struct addr_info* ai_lst, unsigned short port,
1471                                                                 char proto, char *usename,
1472                                                                 unsigned short useport, char *sockname,
1473                                                                 enum si_flags flags,
1474                                                                 struct socket_info** list)
1475 {
1476         struct addr_info* ail;
1477
1478         for (ail=ai_lst; ail; ail=ail->next){
1479                 if(new_sock2list(ail->name.s, 0, port, proto, usename, useport, sockname,
1480                                         ail->flags | flags, list)==0)
1481                         return -1;
1482         }
1483         return 0;
1484 }
1485
1486
1487
1488 /* insert new elements to a socket_info list after "el",
1489  * each element is created from addr_info_lst + port, * protocol and flags
1490  * return 0 on succes, -1 on error
1491  */
1492 static int addr_info_to_si_lst_after(struct addr_info* ai_lst,
1493                                                                                 unsigned short port,
1494                                                                                 char proto,
1495                                                                                 char *usename,
1496                                                                                 unsigned short useport,
1497                                                                                 char *sockname,
1498                                                                                 enum si_flags flags,
1499                                                                                 struct socket_info* el)
1500 {
1501         struct addr_info* ail;
1502         struct socket_info* new_si;
1503
1504         for (ail=ai_lst; ail; ail=ail->next){
1505                 if((new_si=new_sock2list_after(ail->name.s, 0, port, proto,
1506                                                                 usename, useport, sockname,
1507                                                                 ail->flags | flags, el))==0)
1508                         return -1;
1509                 el=new_si;
1510         }
1511         return 0;
1512 }
1513
1514
1515
1516 /* fixes a socket list => resolve addresses,
1517  * interface names, fills missing members, remove duplicates
1518  * fills type_flags if not null with SOCKET_T_IPV4 and/or SOCKET_T_IPV6*/
1519 static int fix_socket_list(struct socket_info **list, int* type_flags)
1520 {
1521         struct socket_info* si;
1522         struct socket_info* new_si;
1523         struct socket_info* l;
1524         struct socket_info* next;
1525         struct socket_info* next_si;
1526         struct socket_info* del_si;
1527         struct socket_info* keep_si;
1528         char* tmp;
1529         int len;
1530         struct addr_info* ai_lst;
1531         struct addr_info* ail;
1532         struct addr_info* tmp_ail;
1533         struct addr_info* tmp_ail_next;
1534         struct addr_info* ail_next;
1535
1536         if (type_flags)
1537                 *type_flags=0;
1538         /* try to change all the interface names into addresses
1539          *  --ugly hack */
1540         for (si=*list;si;){
1541                 next=si->next;
1542                 ai_lst=0;
1543                 if (add_interfaces(si->name.s, auto_bind_ipv6 ? 0 : AF_INET,
1544                                                         si->port_no, si->proto, &ai_lst)!=-1){
1545                         if (si->flags & SI_IS_MHOMED){
1546                                 if((new_si=new_sock2list_after(ai_lst->name.s, 0, si->port_no,
1547                                                                                         si->proto, si->useinfo.name.s,
1548                                                                                         si->useinfo.port_no, si->sockname.s,
1549                                                                                         ai_lst->flags|si->flags, si))==0)
1550                                         break;
1551                                 ail=ai_lst;
1552                                 ai_lst=ai_lst->next;
1553                                 free_addr_info(ail); /* free the first elem. */
1554                                 if (ai_lst){
1555                                         ai_lst->prev=0;
1556                                         /* find the end */
1557                                         for (ail=ai_lst; ail->next; ail=ail->next);
1558                                         /* add the mh list after the last position in ai_lst */
1559                                         addr_info_list_ins_lst(si->addr_info_lst, ail);
1560                                         new_si->addr_info_lst=ai_lst;
1561                                         si->addr_info_lst=0; /* detached and moved to new_si */
1562                                         ail=ail->next; /* ail== old si->addr_info_lst */
1563                                 }else{
1564                                         ail=si->addr_info_lst;
1565                                         new_si->addr_info_lst=ail;
1566                                         si->addr_info_lst=0; /* detached and moved to new_si */
1567                                 }
1568                         }else{
1569                                 /* add all addr. as separate  interfaces */
1570                                 if (addr_info_to_si_lst_after(ai_lst, si->port_no, si->proto,
1571                                                         si->useinfo.name.s, si->useinfo.port_no,
1572                                                         si->sockname.s, si->flags, si)!=0)
1573                                         goto error;
1574                                 /* ai_lst not needed anymore */
1575                                 free_addr_info_lst(&ai_lst);
1576                                 ail=0;
1577                                 new_si=0;
1578                         }
1579                         /* success => remove current entry (shift the entire array)*/
1580                         sock_listrm(list, si);
1581                         free_sock_info(si);
1582                 }else{
1583                         new_si=si;
1584                         ail=si->addr_info_lst;
1585                 }
1586
1587                 if (ail){
1588                         if (new_si && (new_si->flags & SI_IS_MHOMED)){
1589                                 ai_lst=0;
1590                                 for (; ail;){
1591                                         ail_next=ail->next;
1592                                         if (add_interfaces(ail->name.s, AF_INET, new_si->port_no,
1593                                                                                         new_si->proto, &ai_lst)!=-1){
1594                                                 /* add the resolved list after the current position */
1595                                                 addr_info_list_ins_lst(ai_lst, ail);
1596                                                 /* success, remove the current entity */
1597                                                 addr_info_listrm(&new_si->addr_info_lst, ail);
1598                                                 free_addr_info(ail);
1599                                                 ai_lst=0;
1600                                         }
1601                                         ail=ail_next;
1602                                 }
1603                         }
1604                 }
1605                 si=next;
1606         }
1607         /* get ips & fill the port numbers*/
1608 #ifdef EXTRA_DEBUG
1609         LM_DBG("Listening on\n");
1610 #endif
1611         for (si=*list;si;si=si->next){
1612                 /* fix port number, port_no should be !=0 here */
1613                 if (si->port_no==0){
1614 #ifdef USE_TLS
1615                         si->port_no= (si->proto==PROTO_TLS)?tls_port_no:port_no;
1616 #else
1617                         si->port_no= port_no;
1618 #endif
1619                 }
1620                 tmp=int2str(si->port_no, &len);
1621                 if (len>=MAX_PORT_LEN){
1622                         LM_ERR("bad port number: %d\n", si->port_no);
1623                         goto error;
1624                 }
1625                 si->port_no_str.s=(char*)pkg_malloc(len+1);
1626                 if (si->port_no_str.s==0){
1627                         PKG_MEM_ERROR;
1628                         goto error;
1629                 }
1630                 strncpy(si->port_no_str.s, tmp, len+1);
1631                 si->port_no_str.len=len;
1632
1633                 if (fix_hostname(&si->name, &si->address, &si->address_str,
1634                                                 &si->flags, type_flags, si) !=0 )
1635                         goto error;
1636                 /* fix hostnames in mh addresses */
1637                 for (ail=si->addr_info_lst; ail; ail=ail->next){
1638                         if (fix_hostname(&ail->name, &ail->address, &ail->address_str,
1639                                                 &ail->flags, type_flags, si) !=0 )
1640                                 goto error;
1641                 }
1642
1643                 if (fix_sock_str(si) < 0) goto error;
1644
1645 #ifdef EXTRA_DEBUG
1646                 printf("              %.*s [%s]:%s%s\n", si->name.len,
1647                                 si->name.s, si->address_str.s, si->port_no_str.s,
1648                                 si->flags & SI_IS_MCAST ? " mcast" : "");
1649 #endif
1650         }
1651         /* removing duplicate addresses*/
1652         for (si=*list;si; ){
1653                 next_si=si->next;
1654                 for (l=si->next;l;){
1655                         next=l->next;
1656                         if ((si->port_no==l->port_no) &&
1657                                 (si->address.af==l->address.af) &&
1658                                 (memcmp(si->address.u.addr, l->address.u.addr,
1659                                                 si->address.len) == 0)
1660                                 ){
1661                                 /* remove the socket with no  extra addresses.,
1662                                  * if both of them have extra addresses, remove one of them
1663                                  * and merge the extra addresses into the other */
1664                                 if (l->addr_info_lst==0){
1665                                         del_si=l;
1666                                         keep_si=si;
1667                                 }else if (si->addr_info_lst==0){
1668                                         del_si=si;
1669                                         keep_si=l;
1670                                 }else{
1671                                         /* move l->addr_info_lst to si->addr_info_lst */
1672                                         /* find last elem */
1673                                         for (ail=si->addr_info_lst; ail->next; ail=ail->next);
1674                                         /* add the l list after the last position in si lst */
1675                                         addr_info_list_ins_lst(l->addr_info_lst, ail);
1676                                         l->addr_info_lst=0; /* detached */
1677                                         del_si=l; /* l will be removed */
1678                                         keep_si=l;
1679                                 }
1680 #ifdef EXTRA_DEBUG
1681                                 printf("removing duplicate %s [%s] ==  %s [%s]\n",
1682                                                 keep_si->name.s, keep_si->address_str.s,
1683                                                  del_si->name.s, del_si->address_str.s);
1684 #endif
1685                                 /* add the name to the alias list*/
1686                                 if ((!(del_si->flags& SI_IS_IP)) && (
1687                                                 (del_si->name.len!=keep_si->name.len)||
1688                                                 (strncmp(del_si->name.s, keep_si->name.s,
1689                                                                  del_si->name.len)!=0))
1690                                         )
1691                                         add_alias(del_si->name.s, del_si->name.len,
1692                                                                 l->port_no, l->proto);
1693                                 /* make sure next_si doesn't point to del_si */
1694                                 if (del_si==next_si)
1695                                         next_si=next_si->next;
1696                                 /* remove del_si*/
1697                                 sock_listrm(list, del_si);
1698                                 free_sock_info(del_si);
1699                         }
1700                         l=next;
1701                 }
1702                 si=next_si;
1703         }
1704         /* check for duplicates in extra_addresses */
1705         for (si=*list;si; si=si->next){
1706                 /* check  for & remove internal duplicates: */
1707                 for (ail=si->addr_info_lst; ail;){
1708                         ail_next=ail->next;
1709                         /* 1. check if the extra addresses contain a duplicate for the
1710                          * main  one */
1711                         if ((ail->address.af==si->address.af) &&
1712                                 (memcmp(ail->address.u.addr, si->address.u.addr,
1713                                                         ail->address.len) == 0)){
1714                                 /* add the name to the alias list*/
1715                                 if ((!(ail->flags& SI_IS_IP)) && (
1716                                         (ail->name.len!=si->name.len)||
1717                                         (strncmp(ail->name.s, si->name.s, ail->name.len)!=0)))
1718                                         add_alias(ail->name.s, ail->name.len, si->port_no,
1719                                                                 si->proto);
1720                                         /* remove ail*/
1721                                 addr_info_listrm(&si->addr_info_lst, ail);
1722                                 free_addr_info(ail);
1723                                 ail=ail_next;
1724                                 continue;
1725                         }
1726                         /* 2. check if the extra addresses contain a duplicates for
1727                          *  other addresses in the same list */
1728                         for (tmp_ail=ail->next; tmp_ail;){
1729                                 tmp_ail_next=tmp_ail->next;
1730                                 if ((ail->address.af==tmp_ail->address.af) &&
1731                                         (memcmp(ail->address.u.addr, tmp_ail->address.u.addr,
1732                                                         ail->address.len) == 0)){
1733                                         /* add the name to the alias list*/
1734                                         if ((!(tmp_ail->flags& SI_IS_IP)) && (
1735                                                 (ail->name.len!=tmp_ail->name.len)||
1736                                                 (strncmp(ail->name.s, tmp_ail->name.s,
1737                                                                                 tmp_ail->name.len)!=0))
1738                                                 )
1739                                                 add_alias(tmp_ail->name.s, tmp_ail->name.len,
1740                                                                         si->port_no, si->proto);
1741                                                 /* remove tmp_ail*/
1742                                         addr_info_listrm(&si->addr_info_lst, tmp_ail);
1743                                         if(ail_next==tmp_ail) {
1744                                                 ail_next = tmp_ail_next;
1745                                         }
1746                                         free_addr_info(tmp_ail);
1747                                 }
1748                                 tmp_ail=tmp_ail_next;
1749                         }
1750                         ail=ail_next;
1751                 }
1752                 /* check for duplicates between extra addresses (e.g. sctp MH)
1753                  * and other main addresses, on conflict remove the corresponding
1754                  * extra addresses (another possible solution would be to join
1755                  * the 2 si entries into one). */
1756                 for (ail=si->addr_info_lst; ail;){
1757                         ail_next=ail->next;
1758                         for (l=*list;l; l=l->next){
1759                                 if (l==si) continue;
1760                                 if (si->port_no==l->port_no){
1761                                         if ((ail->address.af==l->address.af) &&
1762                                                 (memcmp(ail->address.u.addr, l->address.u.addr,
1763                                                                                 ail->address.len) == 0)){
1764                                                 /* add the name to the alias list*/
1765                                                 if ((!(ail->flags& SI_IS_IP)) && (
1766                                                         (ail->name.len!=l->name.len)||
1767                                                         (strncmp(ail->name.s, l->name.s, l->name.len)!=0))
1768                                                         )
1769                                                         add_alias(ail->name.s, ail->name.len,
1770                                                                                 l->port_no, l->proto);
1771                                                 /* remove ail*/
1772                                                 addr_info_listrm(&si->addr_info_lst, ail);
1773                                                 free_addr_info(ail);
1774                                                 break;
1775                                         }
1776                                         /* check for duplicates with other  extra addresses
1777                                          * lists */
1778                                         for (tmp_ail=l->addr_info_lst; tmp_ail; ){
1779                                                 tmp_ail_next=tmp_ail->next;
1780                                                 if ((ail->address.af==tmp_ail->address.af) &&
1781                                                         (memcmp(ail->address.u.addr,
1782                                                                         tmp_ail->address.u.addr,
1783                                                                         ail->address.len) == 0)){
1784                                                         /* add the name to the alias list*/
1785                                                         if ((!(tmp_ail->flags& SI_IS_IP)) && (
1786                                                                         (ail->name.len!=tmp_ail->name.len)||
1787                                                                         (strncmp(ail->name.s, tmp_ail->name.s,
1788                                                                                         tmp_ail->name.len)!=0))
1789                                                                 )
1790                                                                 add_alias(tmp_ail->name.s, tmp_ail->name.len,
1791                                                                                 l->port_no, l->proto);
1792                                                         /* remove tmp_ail*/
1793                                                         addr_info_listrm(&l->addr_info_lst, tmp_ail);
1794                                                         free_addr_info(tmp_ail);
1795                                                 }
1796                                                 tmp_ail=tmp_ail_next;
1797                                         }
1798                                 }
1799                         }
1800                         ail=ail_next;
1801                 }
1802         }
1803
1804 #ifdef USE_MCAST
1805              /* Remove invalid multicast entries */
1806         si=*list;
1807         while(si){
1808                 if ((si->proto == PROTO_TCP)
1809 #ifdef USE_TLS
1810                     || (si->proto == PROTO_TLS)
1811 #endif /* USE_TLS */
1812 #ifdef USE_SCTP
1813                         || (si->proto == PROTO_SCTP)
1814 #endif
1815                         ){
1816                         if (si->flags & SI_IS_MCAST){
1817                                 LM_WARN("removing entry %s:%s [%s]:%s\n",
1818                                         get_valid_proto_name(si->proto), si->name.s,
1819                                         si->address_str.s, si->port_no_str.s);
1820                                 l = si;
1821                                 si=si->next;
1822                                 sock_listrm(list, l);
1823                                 free_sock_info(l);
1824                         }else{
1825                                 ail=si->addr_info_lst;
1826                                 while(ail){
1827                                         if (ail->flags & SI_IS_MCAST){
1828                                                 LM_WARN("removing mh entry %s:%s"
1829                                                                 " [%s]:%s\n",
1830                                                                 get_valid_proto_name(si->proto), ail->name.s,
1831                                                                 ail->address_str.s, si->port_no_str.s);
1832                                                 tmp_ail=ail;
1833                                                 ail=ail->next;
1834                                                 addr_info_listrm(&si->addr_info_lst, tmp_ail);
1835                                                 free_addr_info(tmp_ail);
1836                                         }else{
1837                                                 ail=ail->next;
1838                                         }
1839                                 }
1840                                 si=si->next;
1841                         }
1842                 } else {
1843                         si=si->next;
1844                 }
1845         }
1846 #endif /* USE_MCAST */
1847
1848         return 0;
1849 error:
1850         return -1;
1851 }
1852
1853 int socket_types = 0;
1854
1855 /* fix all 3 socket lists, fills socket_types if non-null
1856  * return 0 on success, -1 on error */
1857 int fix_all_socket_lists()
1858 {
1859         struct utsname myname;
1860         int flags;
1861         struct addr_info* ai_lst;
1862
1863         ai_lst=0;
1864
1865         if ((udp_listen==0)
1866 #ifdef USE_TCP
1867                         && (tcp_listen==0)
1868 #ifdef USE_TLS
1869                         && (tls_listen==0)
1870 #endif
1871 #endif
1872 #ifdef USE_SCTP
1873                         && (sctp_listen==0)
1874 #endif
1875                 ){
1876                 /* get all listening ipv4/ipv6 interfaces */
1877                 if ( ( (add_interfaces(0, AF_INET, 0,  PROTO_UDP, &ai_lst)==0)
1878 #ifdef __OS_linux
1879                 &&  (!auto_bind_ipv6 || add_interfaces_via_netlink(0, AF_INET6, 0, PROTO_UDP, &ai_lst) == 0)
1880 #else
1881                 && ( !auto_bind_ipv6 || add_interfaces(0, AF_INET6, 0,  PROTO_UDP, &ai_lst) ==0 ) /* add_interface does not work for IPv6 on Linux */
1882 #endif /* __OS_linux */
1883                          ) && (addr_info_to_si_lst(ai_lst, 0, PROTO_UDP, 0, 0, 0, 0, &udp_listen)==0)){
1884                         free_addr_info_lst(&ai_lst);
1885                         ai_lst=0;
1886                         /* if ok, try to add the others too */
1887 #ifdef USE_TCP
1888                         if (!tcp_disable){
1889                                 if ( ((add_interfaces(0, AF_INET, 0,  PROTO_TCP, &ai_lst)!=0)
1890 #ifdef __OS_linux
1891                                 || (auto_bind_ipv6 && add_interfaces_via_netlink(0, AF_INET6, 0, PROTO_TCP, &ai_lst) != 0)
1892 #else
1893                                 || (auto_bind_ipv6 && add_interfaces(0, AF_INET6, 0,  PROTO_TCP, &ai_lst) !=0 )
1894 #endif /* __OS_linux */
1895                                 ) || (addr_info_to_si_lst(ai_lst, 0, PROTO_TCP, 0, 0, 0, 0,
1896                                                                                                                 &tcp_listen)!=0))
1897                                         goto error;
1898                                 free_addr_info_lst(&ai_lst);
1899                                 ai_lst=0;
1900 #ifdef USE_TLS
1901                                 if (!tls_disable){
1902                                         if (((add_interfaces(0, AF_INET, 0, PROTO_TLS,
1903                                                                                 &ai_lst)!=0)
1904 #ifdef __OS_linux
1905                                 || (auto_bind_ipv6 && add_interfaces_via_netlink(0, AF_INET6, 0, PROTO_TLS, &ai_lst) != 0)
1906 #else
1907                                 || (auto_bind_ipv6 && add_interfaces(0, AF_INET6, 0,  PROTO_TLS, &ai_lst)!=0)
1908 #endif /* __OS_linux */
1909                                         ) || (addr_info_to_si_lst(ai_lst, 0, PROTO_TLS, 0, 0, 0, 0,
1910                                                                                                                 &tls_listen)!=0))
1911                                                 goto error;
1912                                 }
1913                                 free_addr_info_lst(&ai_lst);
1914                                 ai_lst=0;
1915 #endif
1916                         }
1917 #endif
1918 #ifdef USE_SCTP
1919                         if (!sctp_disable){
1920                                 if (((add_interfaces(0, AF_INET, 0,  PROTO_SCTP, &ai_lst)!=0)
1921 #ifdef __OS_linux
1922                                 || (auto_bind_ipv6 && add_interfaces_via_netlink(0, AF_INET6, 0, PROTO_SCTP, &ai_lst) != 0)
1923 #else
1924                                 || (auto_bind_ipv6 && add_interfaces(0, AF_INET6, 0,  PROTO_SCTP, &ai_lst) != 0)
1925 #endif /* __OS_linux */
1926                                         ) || (addr_info_to_si_lst(ai_lst, 0, PROTO_SCTP, 0, 0, 0, 0,
1927                                                                                         &sctp_listen)!=0))
1928                                         goto error;
1929                                 free_addr_info_lst(&ai_lst);
1930                                 ai_lst=0;
1931                         }
1932 #endif /* USE_SCTP */
1933                 }else{
1934                         /* if error fall back to get hostname */
1935                         /* get our address, only the first one */
1936                         if (uname (&myname) <0){
1937                                 LM_ERR("cannot determine hostname, try -l address\n");
1938                                 goto error;
1939                         }
1940                         if (add_listen_iface(myname.nodename, 0, 0, 0, 0)!=0){
1941                                 LM_ERR("add_listen_iface failed \n");
1942                                 goto error;
1943                         }
1944                 }
1945         }
1946         flags=0;
1947         if (fix_socket_list(&udp_listen, &flags)!=0){
1948                 LM_ERR("fix_socket_list udp failed\n");
1949                 goto error;
1950         }
1951         if (flags){
1952                 socket_types|=flags|SOCKET_T_UDP;
1953         }
1954 #ifdef USE_TCP
1955         flags=0;
1956         if (!tcp_disable && (fix_socket_list(&tcp_listen, &flags)!=0)){
1957                 LM_ERR("fix_socket_list tcp failed\n");
1958                 goto error;
1959         }
1960         if (flags){
1961                 socket_types|=flags|SOCKET_T_TCP;
1962         }
1963 #ifdef USE_TLS
1964         flags=0;
1965         if (!tls_disable && (fix_socket_list(&tls_listen, &flags)!=0)){
1966                 LM_ERR("fix_socket_list tls failed\n");
1967                 goto error;
1968         }
1969         if (flags){
1970                 socket_types|=flags|SOCKET_T_TLS;
1971         }
1972 #endif
1973 #endif
1974 #ifdef USE_SCTP
1975         flags=0;
1976         if (!sctp_disable && (fix_socket_list(&sctp_listen, &flags)!=0)){
1977                 LM_ERR("fix_socket_list sctp failed\n");
1978                 goto error;
1979         }
1980         if (flags){
1981                 socket_types|=flags|SOCKET_T_SCTP;
1982         }
1983 #endif /* USE_SCTP */
1984         if ((udp_listen==0)
1985 #ifdef USE_TCP
1986                         && (tcp_listen==0)
1987 #ifdef USE_TLS
1988                         && (tls_listen==0)
1989 #endif
1990 #endif
1991 #ifdef USE_SCTP
1992                         && (sctp_listen==0)
1993 #endif
1994                 ){
1995                 LM_ERR("no listening sockets\n");
1996                 goto error;
1997         }
1998         return 0;
1999 error:
2000         if (ai_lst) free_addr_info_lst(&ai_lst);
2001         return -1;
2002 }
2003
2004
2005
2006 void print_all_socket_lists()
2007 {
2008         struct socket_info *si;
2009         struct socket_info** list;
2010         struct addr_info* ai;
2011         unsigned short proto;
2012
2013         proto=PROTO_UDP;
2014         do{
2015                 list=get_sock_info_list(proto);
2016                 for(si=list?*list:0; si; si=si->next){
2017                         if (si->addr_info_lst){
2018                                 printf("             %s: (%s",
2019                                                 get_valid_proto_name(proto),
2020                                                 si->address_str.s);
2021                                 for (ai=si->addr_info_lst; ai; ai=ai->next) {
2022                                         printf(", %s", ai->address_str.s);
2023                                 }
2024                                 printf("):%s%s%s\n",
2025                                                 si->port_no_str.s,
2026                                                 si->flags & SI_IS_MCAST ? " mcast" : "",
2027                                                 si->flags & SI_IS_MHOMED? " mhomed" : "");
2028                         }else{
2029                                 printf("             %s: %s",
2030                                                 get_valid_proto_name(proto),
2031                                                 si->name.s);
2032                                 if (!(si->flags & SI_IS_IP)) {
2033                                         printf(" [%s]", si->address_str.s);
2034                                 }
2035                                 printf( ":%s%s%s",
2036                                                 si->port_no_str.s,
2037                                                 si->flags & SI_IS_MCAST ? " mcast" : "",
2038                                                 si->flags & SI_IS_MHOMED? " mhomed" : "");
2039                                 if (si->sockname.s) {
2040                                         printf(" name %s", si->sockname.s);
2041                                 }
2042                                 if (si->useinfo.name.s) {
2043                                         printf(" advertise %s:%d", si->useinfo.name.s, si->useinfo.port_no);
2044                                 }
2045                                 printf("\n");
2046                         }
2047                 }
2048         }while((proto=next_proto(proto)));
2049 }
2050
2051
2052 void print_aliases()
2053 {
2054         struct host_alias* a;
2055
2056         for(a=aliases; a; a=a->next) {
2057                 if (a->port) {
2058                         printf("             %s: %.*s:%d\n", get_valid_proto_name(a->proto),
2059                                         a->alias.len, a->alias.s, a->port);
2060                 } else {
2061                         printf("             %s: %.*s:*\n", get_valid_proto_name(a->proto),
2062                                         a->alias.len, a->alias.s);
2063                 }
2064         }
2065 }
2066
2067
2068
2069 void init_proto_order()
2070 {
2071         int r;
2072
2073         /* fix proto list  (remove disabled protocols)*/
2074 #ifdef USE_TCP
2075         if (tcp_disable)
2076 #endif
2077                 for(r=PROTO_NONE; r<=PROTO_LAST; r++){
2078                         if (nxt_proto[r]==PROTO_TCP)
2079                                 nxt_proto[r]=nxt_proto[PROTO_TCP];
2080                 }
2081 #ifdef USE_TCP
2082 #ifdef USE_TLS
2083         if (tls_disable || tcp_disable)
2084 #endif
2085 #endif
2086                 for(r=PROTO_NONE; r<=PROTO_LAST; r++){
2087                         if (nxt_proto[r]==PROTO_TLS)
2088                                 nxt_proto[r]=nxt_proto[PROTO_TLS];
2089                 }
2090 #ifdef USE_SCTP
2091         if (sctp_disable)
2092 #endif
2093                 for(r=PROTO_NONE; r<=PROTO_LAST; r++){
2094                         if (nxt_proto[r]==PROTO_SCTP)
2095                                 nxt_proto[r]=nxt_proto[PROTO_SCTP];
2096                 }
2097
2098         /* Deliberately skipping PROTO_WS and PROTO_WSS here as these
2099            are just upgraded TCP and TLS connections */
2100 }
2101
2102
2103 /**
2104  * parse '[port:]host[:port]' string to a broken down structure
2105  */
2106 int parse_protohostport(str* ins, sr_phostp_t *r)
2107 {
2108         char* first; /* first ':' occurrence */
2109         char* second; /* second ':' occurrence */
2110         char* p;
2111         int bracket;
2112         str tmp=STR_NULL;
2113
2114         first=second=0;
2115         bracket=0;
2116         memset(r, 0, sizeof(sr_phostp_t));
2117
2118         /* find the first 2 ':', ignoring possible ipv6 addresses
2119          * (substrings between [])
2120          */
2121         for(p=ins->s; p<ins->s+ins->len; p++){
2122                 switch(*p){
2123                         case '[':
2124                                 bracket++;
2125                                 if (bracket>1) goto error_brackets;
2126                                 break;
2127                         case ']':
2128                                 bracket--;
2129                                 if (bracket<0) goto error_brackets;
2130                                 break;
2131                         case ':':
2132                                 if (bracket==0){
2133                                         if (first==0) first=p;
2134                                         else if( second==0) second=p;
2135                                         else goto error_colons;
2136                                 }
2137                                 break;
2138                 }
2139         }
2140         if (p==ins->s) return -1;
2141         if (*(p-1)==':') goto error_colons;
2142
2143         if (first==0) { /* no ':' => only host */
2144                 r->host.s=ins->s;
2145                 r->host.len=(int)(p-ins->s);
2146                 goto end;
2147         }
2148         if (second) { /* 2 ':' found => check if valid */
2149                 if (parse_proto((unsigned char*)ins->s, first-ins->s, &r->proto)<0)
2150                         goto error_proto;
2151
2152                 tmp.s=second+1;
2153                 tmp.len=(ins->s + ins->len) - tmp.s;
2154
2155                 if (str2int(&tmp, (unsigned int *)&(r->port))<0) goto error_port;
2156
2157                 r->host.s=first+1;
2158                 r->host.len=(int)(second-r->host.s);
2159                 goto end;
2160         }
2161         /* only 1 ':' found => it's either proto:host or host:port */
2162         tmp.s=first+1;
2163         tmp.len=(ins->s + ins->len) - tmp.s;
2164         if (str2int(&tmp, (unsigned int *)&(r->port))<0) {
2165                 /* invalid port => it's proto:host */
2166                 if (parse_proto((unsigned char*)ins->s, first-ins->s, &r->proto)<0)
2167                         goto error_proto;
2168                 r->host.s=first+1;
2169                 r->host.len=(int)(p-r->host.s);
2170         }else{
2171                 /* valid port => its host:port */
2172                 r->host.s=ins->s;
2173                 r->host.len=(int)(first-r->host.s);
2174         }
2175 end:
2176         return 0;
2177 error_brackets:
2178         LM_ERR("too many brackets in %.*s\n", ins->len, ins->s);
2179         return -1;
2180 error_colons:
2181         LM_ERR("too many colons in %.*s\n", ins->len, ins->s);
2182         return -1;
2183 error_proto:
2184         LM_ERR("bad protocol in %.*s\n", ins->len, ins->s);
2185         return -1;
2186 error_port:
2187         LM_ERR("bad port number in %.*s\n", ins->len, ins->s);
2188         return -1;
2189 }
2190
2191 /**
2192  * lookup a local socket by '[port:]host[:port]' string
2193  */
2194 struct socket_info* lookup_local_socket(str *phostp)
2195 {
2196         sr_phostp_t r;
2197         if(parse_protohostport(phostp, &r)<0)
2198                 return NULL;
2199         return grep_sock_info(&r.host, (unsigned short)r.port,
2200                         (unsigned short)r.proto);
2201 }