Coverage Report

Created: 2023-11-19 07:01

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