Wed Jan 8 2020 09:49:39

Asterisk developer's documentation


acl.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Various sorts of access control
22  *
23  * \author Mark Spencer <markster@digium.com>
24  */
25 
26 /*** MODULEINFO
27  <support_level>core</support_level>
28  ***/
29 
30 #include "asterisk.h"
31 
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 428424 $")
33 
34 #include "asterisk/network.h"
35 
36 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__Darwin__)
37 #include <fcntl.h>
38 #include <net/route.h>
39 #endif
40 
41 #if defined(SOLARIS)
42 #include <sys/sockio.h>
43 #include <net/if.h>
44 #elif defined(HAVE_GETIFADDRS)
45 #include <ifaddrs.h>
46 #endif
47 
48 #include "asterisk/acl.h"
49 #include "asterisk/channel.h"
50 #include "asterisk/utils.h"
51 #include "asterisk/lock.h"
52 #include "asterisk/srv.h"
53 
54 #if (!defined(SOLARIS) && !defined(HAVE_GETIFADDRS))
55 static int get_local_address(struct ast_sockaddr *ourip)
56 {
57  return -1;
58 }
59 #else
60 static void score_address(const struct sockaddr_in *sin, struct in_addr *best_addr, int *best_score)
61 {
62  const char *address;
63  int score;
64 
65  address = ast_inet_ntoa(sin->sin_addr);
66 
67  /* RFC 1700 alias for the local network */
68  if (address[0] == '0') {
69  score = -25;
70  /* RFC 1700 localnet */
71  } else if (strncmp(address, "127", 3) == 0) {
72  score = -20;
73  /* RFC 1918 non-public address space */
74  } else if (strncmp(address, "10.", 3) == 0) {
75  score = -5;
76  /* RFC 1918 non-public address space */
77  } else if (strncmp(address, "172", 3) == 0) {
78  /* 172.16.0.0 - 172.19.255.255, but not 172.160.0.0 - 172.169.255.255 */
79  if (address[4] == '1' && address[5] >= '6' && address[6] == '.') {
80  score = -5;
81  /* 172.20.0.0 - 172.29.255.255, but not 172.200.0.0 - 172.255.255.255 nor 172.2.0.0 - 172.2.255.255 */
82  } else if (address[4] == '2' && address[6] == '.') {
83  score = -5;
84  /* 172.30.0.0 - 172.31.255.255, but not 172.3.0.0 - 172.3.255.255 */
85  } else if (address[4] == '3' && (address[5] == '0' || address[5] == '1')) {
86  score = -5;
87  /* All other 172 addresses are public */
88  } else {
89  score = 0;
90  }
91  /* RFC 2544 Benchmark test range (198.18.0.0 - 198.19.255.255, but not 198.180.0.0 - 198.199.255.255) */
92  } else if (strncmp(address, "198.1", 5) == 0 && address[5] >= '8' && address[6] == '.') {
93  score = -10;
94  /* RFC 1918 non-public address space */
95  } else if (strncmp(address, "192.168", 7) == 0) {
96  score = -5;
97  /* RFC 3330 Zeroconf network */
98  } else if (strncmp(address, "169.254", 7) == 0) {
99  /*!\note Better score than a test network, but not quite as good as RFC 1918
100  * address space. The reason is that some Linux distributions automatically
101  * configure a Zeroconf address before trying DHCP, so we want to prefer a
102  * DHCP lease to a Zeroconf address.
103  */
104  score = -10;
105  /* RFC 3330 Test network */
106  } else if (strncmp(address, "192.0.2.", 8) == 0) {
107  score = -15;
108  /* Every other address should be publically routable */
109  } else {
110  score = 0;
111  }
112 
113  if (score > *best_score) {
114  *best_score = score;
115  memcpy(best_addr, &sin->sin_addr, sizeof(*best_addr));
116  }
117 }
118 
119 static int get_local_address(struct ast_sockaddr *ourip)
120 {
121  int s, res = -1;
122 #ifdef SOLARIS
123  struct lifreq *ifr = NULL;
124  struct lifnum ifn;
125  struct lifconf ifc;
126  struct sockaddr_in *sa;
127  char *buf = NULL;
128  int bufsz, x;
129 #endif /* SOLARIS */
130 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
131  struct ifaddrs *ifap, *ifaphead;
132  int rtnerr;
133  const struct sockaddr_in *sin;
134 #endif /* BSD_OR_LINUX */
135  struct in_addr best_addr;
136  int best_score = -100;
137  memset(&best_addr, 0, sizeof(best_addr));
138 
139 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
140  rtnerr = getifaddrs(&ifaphead);
141  if (rtnerr) {
142  perror(NULL);
143  return -1;
144  }
145 #endif /* BSD_OR_LINUX */
146 
147  s = socket(AF_INET, SOCK_STREAM, 0);
148 
149  if (s > 0) {
150 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
151  for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) {
152 
153  if (ifap->ifa_addr && ifap->ifa_addr->sa_family == AF_INET) {
154  sin = (const struct sockaddr_in *) ifap->ifa_addr;
155  score_address(sin, &best_addr, &best_score);
156  res = 0;
157 
158  if (best_score == 0) {
159  break;
160  }
161  }
162  }
163 #endif /* BSD_OR_LINUX */
164 
165  /* There is no reason whatsoever that this shouldn't work on Linux or BSD also. */
166 #ifdef SOLARIS
167  /* Get a count of interfaces on the machine */
168  ifn.lifn_family = AF_INET;
169  ifn.lifn_flags = 0;
170  ifn.lifn_count = 0;
171  if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) {
172  close(s);
173  return -1;
174  }
175 
176  bufsz = ifn.lifn_count * sizeof(struct lifreq);
177  if (!(buf = malloc(bufsz))) {
178  close(s);
179  return -1;
180  }
181  memset(buf, 0, bufsz);
182 
183  /* Get a list of interfaces on the machine */
184  ifc.lifc_len = bufsz;
185  ifc.lifc_buf = buf;
186  ifc.lifc_family = AF_INET;
187  ifc.lifc_flags = 0;
188  if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) {
189  close(s);
190  free(buf);
191  return -1;
192  }
193 
194  for (ifr = ifc.lifc_req, x = 0; x < ifn.lifn_count; ifr++, x++) {
195  sa = (struct sockaddr_in *)&(ifr->lifr_addr);
196  score_address(sa, &best_addr, &best_score);
197  res = 0;
198 
199  if (best_score == 0) {
200  break;
201  }
202  }
203 
204  free(buf);
205 #endif /* SOLARIS */
206 
207  close(s);
208  }
209 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
210  freeifaddrs(ifaphead);
211 #endif /* BSD_OR_LINUX */
212 
213  if (res == 0 && ourip) {
214  ast_sockaddr_setnull(ourip);
215  ourip->ss.ss_family = AF_INET;
216  ((struct sockaddr_in *)&ourip->ss)->sin_addr = best_addr;
217  }
218  return res;
219 }
220 #endif /* HAVE_GETIFADDRS */
221 
222 /* Free HA structure */
223 void ast_free_ha(struct ast_ha *ha)
224 {
225  struct ast_ha *hal;
226  while (ha) {
227  hal = ha;
228  ha = ha->next;
229  ast_free(hal);
230  }
231 }
232 
233 /* Copy HA structure */
234 void ast_copy_ha(const struct ast_ha *from, struct ast_ha *to)
235 {
236  ast_sockaddr_copy(&to->addr, &from->addr);
237  ast_sockaddr_copy(&to->netmask, &from->netmask);
238  to->sense = from->sense;
239 }
240 
241 /* Create duplicate of ha structure */
242 static struct ast_ha *ast_duplicate_ha(struct ast_ha *original)
243 {
244  struct ast_ha *new_ha;
245 
246  if ((new_ha = ast_calloc(1, sizeof(*new_ha)))) {
247  /* Copy from original to new object */
248  ast_copy_ha(original, new_ha);
249  }
250 
251  return new_ha;
252 }
253 
254 /* Create duplicate HA link list */
255 /* Used in chan_sip2 templates */
256 struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original)
257 {
258  struct ast_ha *start = original;
259  struct ast_ha *ret = NULL;
260  struct ast_ha *current, *prev = NULL;
261 
262  while (start) {
263  current = ast_duplicate_ha(start); /* Create copy of this object */
264  if (prev) {
265  prev->next = current; /* Link previous to this object */
266  }
267 
268  if (!ret) {
269  ret = current; /* Save starting point */
270  }
271 
272  start = start->next; /* Go to next object */
273  prev = current; /* Save pointer to this object */
274  }
275  return ret; /* Return start of list */
276 }
277 
278 /*!
279  * \brief
280  * Isolate a 32-bit section of an IPv6 address
281  *
282  * An IPv6 address can be divided into 4 32-bit chunks. This gives
283  * easy access to one of these chunks.
284  *
285  * \param sin6 A pointer to a struct sockaddr_in6
286  * \param index Which 32-bit chunk to operate on. Must be in the range 0-3.
287  */
288 #define V6_WORD(sin6, index) ((uint32_t *)&((sin6)->sin6_addr))[(index)]
289 
290 /*!
291  * \brief
292  * Apply a netmask to an address and store the result in a separate structure.
293  *
294  * When dealing with IPv6 addresses, one cannot apply a netmask with a simple
295  * logical and operation. Furthermore, the incoming address may be an IPv4 address
296  * and need to be mapped properly before attempting to apply a rule.
297  *
298  * \param addr The IP address to apply the mask to.
299  * \param netmask The netmask configured in the host access rule.
300  * \param result The resultant address after applying the netmask to the given address
301  * \retval 0 Successfully applied netmask
302  * \reval -1 Failed to apply netmask
303  */
304 static int apply_netmask(const struct ast_sockaddr *addr, const struct ast_sockaddr *netmask,
305  struct ast_sockaddr *result)
306 {
307  int res = 0;
308 
309  if (ast_sockaddr_is_ipv4(addr)) {
310  struct sockaddr_in result4 = { 0, };
311  struct sockaddr_in *addr4 = (struct sockaddr_in *) &addr->ss;
312  struct sockaddr_in *mask4 = (struct sockaddr_in *) &netmask->ss;
313  result4.sin_family = AF_INET;
314  result4.sin_addr.s_addr = addr4->sin_addr.s_addr & mask4->sin_addr.s_addr;
315  ast_sockaddr_from_sin(result, &result4);
316  } else if (ast_sockaddr_is_ipv6(addr)) {
317  struct sockaddr_in6 result6 = { 0, };
318  struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &addr->ss;
319  struct sockaddr_in6 *mask6 = (struct sockaddr_in6 *) &netmask->ss;
320  int i;
321  result6.sin6_family = AF_INET6;
322  for (i = 0; i < 4; ++i) {
323  V6_WORD(&result6, i) = V6_WORD(addr6, i) & V6_WORD(mask6, i);
324  }
325  memcpy(&result->ss, &result6, sizeof(result6));
326  result->len = sizeof(result6);
327  } else {
328  /* Unsupported address scheme */
329  res = -1;
330  }
331 
332  return res;
333 }
334 
335 /*!
336  * \brief
337  * Parse a netmask in CIDR notation
338  *
339  * \details
340  * For a mask of an IPv4 address, this should be a number between 0 and 32. For
341  * a mask of an IPv6 address, this should be a number between 0 and 128. This
342  * function creates an IPv6 ast_sockaddr from the given netmask. For masks of
343  * IPv4 addresses, this is accomplished by adding 96 to the original netmask.
344  *
345  * \param[out] addr The ast_sockaddr produced from the CIDR netmask
346  * \param is_v4 Tells if the address we are masking is IPv4.
347  * \param mask_str The CIDR mask to convert
348  * \retval -1 Failure
349  * \retval 0 Success
350  */
351 static int parse_cidr_mask(struct ast_sockaddr *addr, int is_v4, const char *mask_str)
352 {
353  int mask;
354 
355  if (sscanf(mask_str, "%30d", &mask) != 1) {
356  return -1;
357  }
358 
359  if (is_v4) {
360  struct sockaddr_in sin;
361  if (mask < 0 || mask > 32) {
362  return -1;
363  }
364  memset(&sin, 0, sizeof(sin));
365  sin.sin_family = AF_INET;
366  /* If mask is 0, then we already have the
367  * appropriate all 0s address in sin from
368  * the above memset.
369  */
370  if (mask != 0) {
371  sin.sin_addr.s_addr = htonl(0xFFFFFFFF << (32 - mask));
372  }
373  ast_sockaddr_from_sin(addr, &sin);
374  } else {
375  struct sockaddr_in6 sin6;
376  int i;
377  if (mask < 0 || mask > 128) {
378  return -1;
379  }
380  memset(&sin6, 0, sizeof(sin6));
381  sin6.sin6_family = AF_INET6;
382  for (i = 0; i < 4; ++i) {
383  /* Once mask reaches 0, we don't have
384  * to explicitly set anything anymore
385  * since sin6 was zeroed out already
386  */
387  if (mask > 0) {
388  V6_WORD(&sin6, i) = htonl(0xFFFFFFFF << (mask < 32 ? (32 - mask) : 0));
389  mask -= mask < 32 ? mask : 32;
390  }
391  }
392  memcpy(&addr->ss, &sin6, sizeof(sin6));
393  addr->len = sizeof(sin6);
394  }
395 
396  return 0;
397 }
398 
399 struct ast_ha *ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error)
400 {
401  struct ast_ha *ha;
402  struct ast_ha *prev = NULL;
403  struct ast_ha *ret;
404  char *tmp = ast_strdupa(stuff);
405  char *address = NULL, *mask = NULL;
406  int addr_is_v4;
407 
408  ret = path;
409  while (path) {
410  prev = path;
411  path = path->next;
412  }
413 
414  if (!(ha = ast_calloc(1, sizeof(*ha)))) {
415  if (error) {
416  *error = 1;
417  }
418  return ret;
419  }
420 
421  address = strsep(&tmp, "/");
422  if (!address) {
423  address = tmp;
424  } else {
425  mask = tmp;
426  }
427 
428  if (!ast_sockaddr_parse(&ha->addr, address, PARSE_PORT_FORBID)) {
429  ast_log(LOG_WARNING, "Invalid IP address: %s\n", address);
430  ast_free_ha(ha);
431  if (error) {
432  *error = 1;
433  }
434  return ret;
435  }
436 
437  /* If someone specifies an IPv4-mapped IPv6 address,
438  * we just convert this to an IPv4 ACL
439  */
440  if (ast_sockaddr_ipv4_mapped(&ha->addr, &ha->addr)) {
441  ast_log(LOG_NOTICE, "IPv4-mapped ACL network address specified. "
442  "Converting to an IPv4 ACL network address.\n");
443  }
444 
445  addr_is_v4 = ast_sockaddr_is_ipv4(&ha->addr);
446 
447  if (!mask) {
448  parse_cidr_mask(&ha->netmask, addr_is_v4, addr_is_v4 ? "32" : "128");
449  } else if (strchr(mask, ':') || strchr(mask, '.')) {
450  int mask_is_v4;
451  /* Mask is of x.x.x.x or x:x:x:x:x:x:x:x variety */
452  if (!ast_sockaddr_parse(&ha->netmask, mask, PARSE_PORT_FORBID)) {
453  ast_log(LOG_WARNING, "Invalid netmask: %s\n", mask);
454  ast_free_ha(ha);
455  if (error) {
456  *error = 1;
457  }
458  return ret;
459  }
460  /* If someone specifies an IPv4-mapped IPv6 netmask,
461  * we just convert this to an IPv4 ACL
462  */
463  if (ast_sockaddr_ipv4_mapped(&ha->netmask, &ha->netmask)) {
464  ast_log(LOG_NOTICE, "IPv4-mapped ACL netmask specified. "
465  "Converting to an IPv4 ACL netmask.\n");
466  }
467  mask_is_v4 = ast_sockaddr_is_ipv4(&ha->netmask);
468  if (addr_is_v4 ^ mask_is_v4) {
469  ast_log(LOG_WARNING, "Address and mask are not using same address scheme.\n");
470  ast_free_ha(ha);
471  if (error) {
472  *error = 1;
473  }
474  return ret;
475  }
476  } else if (parse_cidr_mask(&ha->netmask, addr_is_v4, mask)) {
477  ast_log(LOG_WARNING, "Invalid CIDR netmask: %s\n", mask);
478  ast_free_ha(ha);
479  if (error) {
480  *error = 1;
481  }
482  return ret;
483  }
484 
485  if (apply_netmask(&ha->addr, &ha->netmask, &ha->addr)) {
486  /* This shouldn't happen because ast_sockaddr_parse would
487  * have failed much earlier on an unsupported address scheme
488  */
489  char *failmask = ast_strdupa(ast_sockaddr_stringify(&ha->netmask));
490  char *failaddr = ast_strdupa(ast_sockaddr_stringify(&ha->addr));
491  ast_log(LOG_WARNING, "Unable to apply netmask %s to address %s\n", failmask, failaddr);
492  ast_free_ha(ha);
493  if (error) {
494  *error = 1;
495  }
496  return ret;
497  }
498 
499  ha->sense = strncasecmp(sense, "p", 1) ? AST_SENSE_DENY : AST_SENSE_ALLOW;
500 
501  ha->next = NULL;
502  if (prev) {
503  prev->next = ha;
504  } else {
505  ret = ha;
506  }
507 
508  {
509  const char *addr = ast_strdupa(ast_sockaddr_stringify(&ha->addr));
510  const char *mask = ast_strdupa(ast_sockaddr_stringify(&ha->netmask));
511 
512  ast_debug(1, "%s/%s sense %d appended to acl for peer\n", addr, mask, ha->sense);
513  }
514 
515  return ret;
516 }
517 
518 int ast_apply_ha(const struct ast_ha *ha, const struct ast_sockaddr *addr)
519 {
520  /* Start optimistic */
521  int res = AST_SENSE_ALLOW;
522  const struct ast_ha *current_ha;
523 
524  for (current_ha = ha; current_ha; current_ha = current_ha->next) {
525  struct ast_sockaddr result;
526  struct ast_sockaddr mapped_addr;
527  const struct ast_sockaddr *addr_to_use;
528 #if 0 /* debugging code */
529  char iabuf[INET_ADDRSTRLEN];
530  char iabuf2[INET_ADDRSTRLEN];
531  /* DEBUG */
532  ast_copy_string(iabuf, ast_inet_ntoa(sin->sin_addr), sizeof(iabuf));
533  ast_copy_string(iabuf2, ast_inet_ntoa(ha->netaddr), sizeof(iabuf2));
534  ast_debug(1, "##### Testing %s with %s\n", iabuf, iabuf2);
535 #endif
536  if (ast_sockaddr_is_ipv4(&current_ha->addr)) {
537  if (ast_sockaddr_is_ipv6(addr)) {
538  if (ast_sockaddr_is_ipv4_mapped(addr)) {
539  /* IPv4 ACLs apply to IPv4-mapped addresses */
540  if (!ast_sockaddr_ipv4_mapped(addr, &mapped_addr)) {
541  ast_log(LOG_ERROR, "%s provided to ast_sockaddr_ipv4_mapped could not be converted. That shouldn't be possible.\n",
542  ast_sockaddr_stringify(addr));
543  continue;
544  }
545  addr_to_use = &mapped_addr;
546  } else {
547  /* An IPv4 ACL does not apply to an IPv6 address */
548  continue;
549  }
550  } else {
551  /* Address is IPv4 and ACL is IPv4. No biggie */
552  addr_to_use = addr;
553  }
554  } else {
556  addr_to_use = addr;
557  } else {
558  /* Address is IPv4 or IPv4 mapped but ACL is IPv6. Skip */
559  continue;
560  }
561  }
562 
563  /* For each rule, if this address and the netmask = the net address
564  apply the current rule */
565  if (apply_netmask(addr_to_use, &current_ha->netmask, &result)) {
566  /* Unlikely to happen since we know the address to be IPv4 or IPv6 */
567  continue;
568  }
569  if (!ast_sockaddr_cmp_addr(&result, &current_ha->addr)) {
570  res = current_ha->sense;
571  }
572  }
573  return res;
574 }
575 
576 static int resolve_first(struct ast_sockaddr *addr, const char *name, int flag,
577  int family)
578 {
579  struct ast_sockaddr *addrs;
580  int addrs_cnt;
581 
582  addrs_cnt = ast_sockaddr_resolve(&addrs, name, flag, family);
583  if (addrs_cnt > 0) {
584  if (addrs_cnt > 1) {
585  ast_debug(1, "Multiple addresses. Using the first only\n");
586  }
587  ast_sockaddr_copy(addr, &addrs[0]);
588  ast_free(addrs);
589  } else {
590  ast_log(LOG_WARNING, "Unable to lookup '%s'\n", name);
591  return -1;
592  }
593 
594  return 0;
595 }
596 
597 int ast_get_ip_or_srv(struct ast_sockaddr *addr, const char *hostname, const char *service)
598 {
599  char srv[256];
600  char host[256];
601  int srv_ret = 0;
602  int tportno;
603 
604  if (service) {
605  snprintf(srv, sizeof(srv), "%s.%s", service, hostname);
606  if ((srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno, srv)) > 0) {
607  hostname = host;
608  }
609  }
610 
611  if (resolve_first(addr, hostname, PARSE_PORT_FORBID, addr->ss.ss_family) != 0) {
612  return -1;
613  }
614 
615  if (srv_ret > 0) {
616  ast_sockaddr_set_port(addr, tportno);
617  }
618 
619  return 0;
620 }
621 
623  char *name;
624  unsigned int space;
625 };
626 
627 /* IANA registered DSCP codepoints */
628 
629 static const struct dscp_codepoint dscp_pool1[] = {
630  { "CS0", 0x00 },
631  { "CS1", 0x08 },
632  { "CS2", 0x10 },
633  { "CS3", 0x18 },
634  { "CS4", 0x20 },
635  { "CS5", 0x28 },
636  { "CS6", 0x30 },
637  { "CS7", 0x38 },
638  { "AF11", 0x0A },
639  { "AF12", 0x0C },
640  { "AF13", 0x0E },
641  { "AF21", 0x12 },
642  { "AF22", 0x14 },
643  { "AF23", 0x16 },
644  { "AF31", 0x1A },
645  { "AF32", 0x1C },
646  { "AF33", 0x1E },
647  { "AF41", 0x22 },
648  { "AF42", 0x24 },
649  { "AF43", 0x26 },
650  { "EF", 0x2E },
651 };
652 
653 int ast_str2cos(const char *value, unsigned int *cos)
654 {
655  int fval;
656 
657  if (sscanf(value, "%30d", &fval) == 1) {
658  if (fval < 8) {
659  *cos = fval;
660  return 0;
661  }
662  }
663 
664  return -1;
665 }
666 
667 int ast_str2tos(const char *value, unsigned int *tos)
668 {
669  int fval;
670  unsigned int x;
671 
672  if (sscanf(value, "%30i", &fval) == 1) {
673  *tos = fval & 0xFF;
674  return 0;
675  }
676 
677  for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) {
678  if (!strcasecmp(value, dscp_pool1[x].name)) {
679  *tos = dscp_pool1[x].space << 2;
680  return 0;
681  }
682  }
683 
684  return -1;
685 }
686 
687 const char *ast_tos2str(unsigned int tos)
688 {
689  unsigned int x;
690 
691  for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) {
692  if (dscp_pool1[x].space == (tos >> 2)) {
693  return dscp_pool1[x].name;
694  }
695  }
696 
697  return "unknown";
698 }
699 
700 int ast_get_ip(struct ast_sockaddr *addr, const char *hostname)
701 {
702  return ast_get_ip_or_srv(addr, hostname, NULL);
703 }
704 
705 int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
706 {
707  int port;
708  int s;
709 
710  port = ast_sockaddr_port(us);
711 
712  if ((s = socket(ast_sockaddr_is_ipv6(them) ? AF_INET6 : AF_INET,
713  SOCK_DGRAM, 0)) < 0) {
714  ast_log(LOG_ERROR, "Cannot create socket\n");
715  return -1;
716  }
717 
718  if (ast_connect(s, them)) {
719  ast_log(LOG_WARNING, "Cannot connect\n");
720  close(s);
721  return -1;
722  }
723  if (ast_getsockname(s, us)) {
724 
725  ast_log(LOG_WARNING, "Cannot get socket name\n");
726  close(s);
727  return -1;
728  }
729  close(s);
730 
731  {
732  const char *them_addr = ast_strdupa(ast_sockaddr_stringify_addr(them));
733  const char *us_addr = ast_strdupa(ast_sockaddr_stringify_addr(us));
734 
735  ast_debug(3, "For destination '%s', our source address is '%s'.\n",
736  them_addr, us_addr);
737  }
738 
739  ast_sockaddr_set_port(us, port);
740 
741  return 0;
742 }
743 
744 int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr, int family)
745 {
746  char ourhost[MAXHOSTNAMELEN] = "";
747  struct ast_sockaddr root;
748  int res, port = ast_sockaddr_port(ourip);
749 
750  /* just use the bind address if it is nonzero */
751  if (!ast_sockaddr_is_any(bindaddr)) {
752  ast_sockaddr_copy(ourip, bindaddr);
753  ast_debug(3, "Attached to given IP address\n");
754  return 0;
755  }
756  /* try to use our hostname */
757  if (gethostname(ourhost, sizeof(ourhost) - 1)) {
758  ast_log(LOG_WARNING, "Unable to get hostname\n");
759  } else {
760  if (resolve_first(ourip, ourhost, PARSE_PORT_FORBID, family) == 0) {
761  /* reset port since resolve_first wipes this out */
762  ast_sockaddr_set_port(ourip, port);
763  return 0;
764  }
765  }
766  ast_debug(3, "Trying to check A.ROOT-SERVERS.NET and get our IP address for that connection\n");
767  /* A.ROOT-SERVERS.NET. */
768  if (!resolve_first(&root, "A.ROOT-SERVERS.NET", PARSE_PORT_FORBID, 0) &&
769  !ast_ouraddrfor(&root, ourip)) {
770  /* reset port since resolve_first wipes this out */
771  ast_sockaddr_set_port(ourip, port);
772  return 0;
773  }
774  res = get_local_address(ourip);
775  ast_sockaddr_set_port(ourip, port);
776  return res;
777 }
778 
static char * ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
Definition: netsock2.h:240
struct ast_ha * next
Definition: acl.h:53
struct ast_ha * ast_duplicate_ha_list(struct ast_ha *original)
Duplicate the contents of a list of host access rules.
Definition: acl.c:256
struct sockaddr_storage ss
Definition: netsock2.h:64
static struct dscp_codepoint dscp_pool1[]
Definition: acl.c:629
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
char * strsep(char **str, const char *delims)
char * name
Definition: acl.c:623
#define malloc(a)
Definition: astmm.h:88
static unsigned int tos
Definition: chan_h323.c:146
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:198
int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr, int family)
Find our IP address.
Definition: acl.c:744
struct ast_sockaddr addr
Definition: acl.h:50
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
Definition: netsock2.h:121
int ast_apply_ha(const struct ast_ha *ha, const struct ast_sockaddr *addr)
Apply a set of rules to a given IP address.
Definition: acl.c:518
#define LOG_WARNING
Definition: logger.h:144
Support for DNS SRV records, used in to locate SIP services.
int ast_sockaddr_ipv4_mapped(const struct ast_sockaddr *addr, struct ast_sockaddr *ast_mapped)
Convert an IPv4-mapped IPv6 address into an IPv4 address.
Definition: netsock2.c:39
socklen_t len
Definition: netsock2.h:65
static char ourhost[MAXHOSTNAMELEN]
Definition: chan_mgcp.c:231
enum ast_cc_service_type service
Definition: chan_sip.c:821
static int apply_netmask(const struct ast_sockaddr *addr, const struct ast_sockaddr *netmask, struct ast_sockaddr *result)
Apply a netmask to an address and store the result in a separate structure.
Definition: acl.c:304
#define MAXHOSTNAMELEN
Definition: network.h:69
int ast_str2tos(const char *value, unsigned int *tos)
Convert a string to the appropriate TOS value.
Definition: acl.c:667
static int parse_cidr_mask(struct ast_sockaddr *addr, int is_v4, const char *mask_str)
Parse a netmask in CIDR notation.
Definition: acl.c:351
int value
Definition: syslog.c:39
Socket address structure.
Definition: netsock2.h:63
int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares the addresses of two ast_sockaddr structures.
Definition: netsock2.c:325
static int resolve_first(struct ast_sockaddr *addr, const char *name, int flag, int family)
Definition: acl.c:576
Utility functions.
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:106
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:406
internal representation of acl entries In principle user applications would have no need for this...
Definition: acl.h:48
int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
Get our local IP address when contacting a remote host.
Definition: acl.c:705
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int ast_sockaddr_is_any(const struct ast_sockaddr *addr)
Determine if the address type is unspecified, or &quot;any&quot; address.
Definition: netsock2.c:424
int ast_get_srv(struct ast_channel *chan, char *host, int hostlen, int *port, const char *service)
Definition: srv.c:263
General Asterisk PBX channel definitions.
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
Definition: netsock2.h:642
struct ast_sockaddr netmask
Definition: acl.h:51
Access Control of various sorts.
static void score_address(const struct sockaddr_in *sin, struct in_addr *best_addr, int *best_score)
Definition: acl.c:60
#define AST_SENSE_DENY
Definition: acl.h:35
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
int sense
Definition: acl.h:52
#define LOG_ERROR
Definition: logger.h:155
#define free(a)
Definition: astmm.h:94
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:422
struct ast_sockaddr bindaddr
Definition: chan_sip.c:1146
#define AST_SENSE_ALLOW
Definition: acl.h:36
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:210
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_get_ip(struct ast_sockaddr *addr, const char *hostname)
Get the IP address given a hostname.
Definition: acl.c:700
#define LOG_NOTICE
Definition: logger.h:133
static const char name[]
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:564
#define ast_free(a)
Definition: astmm.h:97
int ast_str2cos(const char *value, unsigned int *cos)
Convert a string to the appropriate COS value.
Definition: acl.c:653
static int get_local_address(struct ast_sockaddr *ourip)
Definition: acl.c:119
int ast_sockaddr_is_ipv4_mapped(const struct ast_sockaddr *addr)
Determine if this is an IPv4-mapped IPv6 address.
Definition: netsock2.c:406
unsigned int space
Definition: acl.c:624
int ast_get_ip_or_srv(struct ast_sockaddr *addr, const char *hostname, const char *service)
Get the IP address given a hostname and optional service.
Definition: acl.c:597
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:223
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:400
struct ast_ha * ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error)
Add a new rule to a list of HAs.
Definition: acl.c:399
int ast_getsockname(int sockfd, struct ast_sockaddr *addr)
Wrapper around getsockname(2) that uses struct ast_sockaddr.
Definition: netsock2.c:472
static unsigned int cos
Definition: chan_h323.c:147
static struct ast_ha * ast_duplicate_ha(struct ast_ha *original)
Definition: acl.c:242
const char * ast_tos2str(unsigned int tos)
Convert a TOS value into its string representation.
Definition: acl.c:687
#define V6_WORD(sin6, index)
Isolate a 32-bit section of an IPv6 address.
Definition: acl.c:288
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:418
int ast_connect(int sockfd, const struct ast_sockaddr *addr)
Wrapper around connect(2) that uses struct ast_sockaddr.
Definition: netsock2.c:467
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str, int flags, int family)
Parses a string with an IPv4 or IPv6 address and place results into an array.
Definition: netsock2.c:248
void ast_copy_ha(const struct ast_ha *from, struct ast_ha *to)
Copy the contents of one HA to another.
Definition: acl.c:234
static char hostname[MAXHOSTNAMELEN]
Definition: logger.c:91