00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "asterisk.h"
00031
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 374632 $")
00033
00034 #include "asterisk/network.h"
00035
00036 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__Darwin__)
00037 #include <fcntl.h>
00038 #include <net/route.h>
00039 #endif
00040
00041 #if defined(SOLARIS)
00042 #include <sys/sockio.h>
00043 #include <net/if.h>
00044 #elif defined(HAVE_GETIFADDRS)
00045 #include <ifaddrs.h>
00046 #endif
00047
00048 #include "asterisk/acl.h"
00049 #include "asterisk/channel.h"
00050 #include "asterisk/utils.h"
00051 #include "asterisk/lock.h"
00052 #include "asterisk/srv.h"
00053
00054 #if (!defined(SOLARIS) && !defined(HAVE_GETIFADDRS))
00055 static int get_local_address(struct ast_sockaddr *ourip)
00056 {
00057 return -1;
00058 }
00059 #else
00060 static void score_address(const struct sockaddr_in *sin, struct in_addr *best_addr, int *best_score)
00061 {
00062 const char *address;
00063 int score;
00064
00065 address = ast_inet_ntoa(sin->sin_addr);
00066
00067
00068 if (address[0] == '0') {
00069 score = -25;
00070
00071 } else if (strncmp(address, "127", 3) == 0) {
00072 score = -20;
00073
00074 } else if (strncmp(address, "10.", 3) == 0) {
00075 score = -5;
00076
00077 } else if (strncmp(address, "172", 3) == 0) {
00078
00079 if (address[4] == '1' && address[5] >= '6' && address[6] == '.') {
00080 score = -5;
00081
00082 } else if (address[4] == '2' && address[6] == '.') {
00083 score = -5;
00084
00085 } else if (address[4] == '3' && (address[5] == '0' || address[5] == '1')) {
00086 score = -5;
00087
00088 } else {
00089 score = 0;
00090 }
00091
00092 } else if (strncmp(address, "198.1", 5) == 0 && address[5] >= '8' && address[6] == '.') {
00093 score = -10;
00094
00095 } else if (strncmp(address, "192.168", 7) == 0) {
00096 score = -5;
00097
00098 } else if (strncmp(address, "169.254", 7) == 0) {
00099
00100
00101
00102
00103
00104 score = -10;
00105
00106 } else if (strncmp(address, "192.0.2.", 8) == 0) {
00107 score = -15;
00108
00109 } else {
00110 score = 0;
00111 }
00112
00113 if (score > *best_score) {
00114 *best_score = score;
00115 memcpy(best_addr, &sin->sin_addr, sizeof(*best_addr));
00116 }
00117 }
00118
00119 static int get_local_address(struct ast_sockaddr *ourip)
00120 {
00121 int s, res = -1;
00122 #ifdef SOLARIS
00123 struct lifreq *ifr = NULL;
00124 struct lifnum ifn;
00125 struct lifconf ifc;
00126 struct sockaddr_in *sa;
00127 char *buf = NULL;
00128 int bufsz, x;
00129 #endif
00130 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__) || defined(__GLIBC__)
00131 struct ifaddrs *ifap, *ifaphead;
00132 int rtnerr;
00133 const struct sockaddr_in *sin;
00134 #endif
00135 struct in_addr best_addr;
00136 int best_score = -100;
00137 memset(&best_addr, 0, sizeof(best_addr));
00138
00139 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__) || defined(__GLIBC__)
00140 rtnerr = getifaddrs(&ifaphead);
00141 if (rtnerr) {
00142 perror(NULL);
00143 return -1;
00144 }
00145 #endif
00146
00147 s = socket(AF_INET, SOCK_STREAM, 0);
00148
00149 if (s > 0) {
00150 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__) || defined(__GLIBC__)
00151 for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) {
00152
00153 if (ifap->ifa_addr && ifap->ifa_addr->sa_family == AF_INET) {
00154 sin = (const struct sockaddr_in *) ifap->ifa_addr;
00155 score_address(sin, &best_addr, &best_score);
00156 res = 0;
00157
00158 if (best_score == 0) {
00159 break;
00160 }
00161 }
00162 }
00163 #endif
00164
00165
00166 #ifdef SOLARIS
00167
00168 ifn.lifn_family = AF_INET;
00169 ifn.lifn_flags = 0;
00170 ifn.lifn_count = 0;
00171 if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) {
00172 close(s);
00173 return -1;
00174 }
00175
00176 bufsz = ifn.lifn_count * sizeof(struct lifreq);
00177 if (!(buf = malloc(bufsz))) {
00178 close(s);
00179 return -1;
00180 }
00181 memset(buf, 0, bufsz);
00182
00183
00184 ifc.lifc_len = bufsz;
00185 ifc.lifc_buf = buf;
00186 ifc.lifc_family = AF_INET;
00187 ifc.lifc_flags = 0;
00188 if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) {
00189 close(s);
00190 free(buf);
00191 return -1;
00192 }
00193
00194 for (ifr = ifc.lifc_req, x = 0; x < ifn.lifn_count; ifr++, x++) {
00195 sa = (struct sockaddr_in *)&(ifr->lifr_addr);
00196 score_address(sa, &best_addr, &best_score);
00197 res = 0;
00198
00199 if (best_score == 0) {
00200 break;
00201 }
00202 }
00203
00204 free(buf);
00205 #endif
00206
00207 close(s);
00208 }
00209 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
00210 freeifaddrs(ifaphead);
00211 #endif
00212
00213 if (res == 0 && ourip) {
00214 ast_sockaddr_setnull(ourip);
00215 ourip->ss.ss_family = AF_INET;
00216 ((struct sockaddr_in *)&ourip->ss)->sin_addr = best_addr;
00217 }
00218 return res;
00219 }
00220 #endif
00221
00222
00223 void ast_free_ha(struct ast_ha *ha)
00224 {
00225 struct ast_ha *hal;
00226 while (ha) {
00227 hal = ha;
00228 ha = ha->next;
00229 ast_free(hal);
00230 }
00231 }
00232
00233
00234 struct ast_acl_list *ast_free_acl_list(struct ast_acl_list *acl_list)
00235 {
00236 struct ast_acl *current;
00237
00238 if (!acl_list) {
00239 return NULL;
00240 }
00241
00242 AST_LIST_LOCK(acl_list);
00243 while ((current = AST_LIST_REMOVE_HEAD(acl_list, list))) {
00244 ast_free_ha(current->acl);
00245 ast_free(current);
00246 }
00247 AST_LIST_UNLOCK(acl_list);
00248
00249 AST_LIST_HEAD_DESTROY(acl_list);
00250 ast_free(acl_list);
00251
00252 return NULL;
00253 }
00254
00255
00256 void ast_copy_ha(const struct ast_ha *from, struct ast_ha *to)
00257 {
00258 ast_sockaddr_copy(&to->addr, &from->addr);
00259 ast_sockaddr_copy(&to->netmask, &from->netmask);
00260 to->sense = from->sense;
00261 }
00262
00263
00264 static struct ast_ha *ast_duplicate_ha(struct ast_ha *original)
00265 {
00266 struct ast_ha *new_ha;
00267
00268 if ((new_ha = ast_calloc(1, sizeof(*new_ha)))) {
00269
00270 ast_copy_ha(original, new_ha);
00271 }
00272
00273 return new_ha;
00274 }
00275
00276
00277
00278 struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original)
00279 {
00280 struct ast_ha *start = original;
00281 struct ast_ha *ret = NULL;
00282 struct ast_ha *current, *prev = NULL;
00283
00284 while (start) {
00285 current = ast_duplicate_ha(start);
00286 if (prev) {
00287 prev->next = current;
00288 }
00289
00290 if (!ret) {
00291 ret = current;
00292 }
00293
00294 start = start->next;
00295 prev = current;
00296 }
00297 return ret;
00298 }
00299
00300 static int acl_new(struct ast_acl **pointer, const char *name) {
00301 struct ast_acl *acl;
00302 if (!(acl = ast_calloc(1, sizeof(*acl)))) {
00303 return 1;
00304 }
00305
00306 *pointer = acl;
00307 ast_copy_string(acl->name, name, ACL_NAME_LENGTH);
00308 return 0;
00309 }
00310
00311 struct ast_acl_list *ast_duplicate_acl_list(struct ast_acl_list *original)
00312 {
00313 struct ast_acl_list *clone;
00314 struct ast_acl *current_cursor;
00315 struct ast_acl *current_clone;
00316
00317
00318 if (!original) {
00319 return NULL;
00320 }
00321
00322 if (!(clone = ast_calloc(1, sizeof(*clone)))) {
00323 ast_log(LOG_WARNING, "Failed to allocate ast_acl_list struct while cloning an ACL\n");
00324 return NULL;
00325 }
00326 AST_LIST_HEAD_INIT(clone);
00327
00328 AST_LIST_LOCK(original);
00329
00330 AST_LIST_TRAVERSE(original, current_cursor, list) {
00331 if ((acl_new(¤t_clone, current_cursor->name))) {
00332 ast_log(LOG_WARNING, "Failed to allocate ast_acl struct while cloning an ACL.");
00333 continue;
00334 }
00335
00336
00337 current_clone->acl = ast_duplicate_ha_list(current_cursor->acl);
00338
00339 current_clone->is_invalid = current_cursor->is_invalid;
00340 current_clone->is_realtime = current_cursor->is_realtime;
00341
00342 AST_LIST_INSERT_TAIL(clone, current_clone, list);
00343 }
00344
00345 AST_LIST_UNLOCK(original);
00346
00347 return clone;
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 #define V6_WORD(sin6, index) ((uint32_t *)&((sin6)->sin6_addr))[(index)]
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 static int apply_netmask(const struct ast_sockaddr *addr, const struct ast_sockaddr *netmask,
00377 struct ast_sockaddr *result)
00378 {
00379 int res = 0;
00380
00381 if (ast_sockaddr_is_ipv4(addr)) {
00382 struct sockaddr_in result4 = { 0, };
00383 struct sockaddr_in *addr4 = (struct sockaddr_in *) &addr->ss;
00384 struct sockaddr_in *mask4 = (struct sockaddr_in *) &netmask->ss;
00385 result4.sin_family = AF_INET;
00386 result4.sin_addr.s_addr = addr4->sin_addr.s_addr & mask4->sin_addr.s_addr;
00387 ast_sockaddr_from_sin(result, &result4);
00388 } else if (ast_sockaddr_is_ipv6(addr)) {
00389 struct sockaddr_in6 result6 = { 0, };
00390 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &addr->ss;
00391 struct sockaddr_in6 *mask6 = (struct sockaddr_in6 *) &netmask->ss;
00392 int i;
00393 result6.sin6_family = AF_INET6;
00394 for (i = 0; i < 4; ++i) {
00395 V6_WORD(&result6, i) = V6_WORD(addr6, i) & V6_WORD(mask6, i);
00396 }
00397 memcpy(&result->ss, &result6, sizeof(result6));
00398 result->len = sizeof(result6);
00399 } else {
00400
00401 res = -1;
00402 }
00403
00404 return res;
00405 }
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 static int parse_cidr_mask(struct ast_sockaddr *addr, int is_v4, const char *mask_str)
00424 {
00425 int mask;
00426
00427 if (sscanf(mask_str, "%30d", &mask) != 1) {
00428 return -1;
00429 }
00430
00431 if (is_v4) {
00432 struct sockaddr_in sin;
00433 if (mask < 0 || mask > 32) {
00434 return -1;
00435 }
00436 memset(&sin, 0, sizeof(sin));
00437 sin.sin_family = AF_INET;
00438
00439
00440
00441
00442 if (mask != 0) {
00443 sin.sin_addr.s_addr = htonl(0xFFFFFFFF << (32 - mask));
00444 }
00445 ast_sockaddr_from_sin(addr, &sin);
00446 } else {
00447 struct sockaddr_in6 sin6;
00448 int i;
00449 if (mask < 0 || mask > 128) {
00450 return -1;
00451 }
00452 memset(&sin6, 0, sizeof(sin6));
00453 sin6.sin6_family = AF_INET6;
00454 for (i = 0; i < 4; ++i) {
00455
00456
00457
00458
00459 if (mask > 0) {
00460 V6_WORD(&sin6, i) = htonl(0xFFFFFFFF << (mask < 32 ? (32 - mask) : 0));
00461 mask -= mask < 32 ? mask : 32;
00462 }
00463 }
00464 memcpy(&addr->ss, &sin6, sizeof(sin6));
00465 addr->len = sizeof(sin6);
00466 }
00467
00468 return 0;
00469 }
00470
00471
00472
00473 void ast_append_acl(const char *sense, const char *stuff, struct ast_acl_list **path, int *error, int *named_acl_flag)
00474 {
00475 struct ast_acl *acl = NULL;
00476 struct ast_acl *current;
00477 struct ast_acl_list *working_list;
00478
00479 char *tmp, *list;
00480
00481
00482 if (*path == NULL) {
00483 struct ast_acl_list *list;
00484 list = ast_calloc(1, sizeof(*list));
00485 if (!list) {
00486
00487 if (error) {
00488 *error = 1;
00489 }
00490 return;
00491 }
00492
00493 AST_LIST_HEAD_INIT(list);
00494 *path = list;
00495 }
00496
00497 working_list = *path;
00498
00499 AST_LIST_LOCK(working_list);
00500
00501
00502 if (strncasecmp(sense, "a", 1)) {
00503
00504
00505 current = AST_LIST_FIRST(working_list);
00506
00507 if (!current || !ast_strlen_zero(current->name)) {
00508 if (acl_new(&acl, "")) {
00509 if (error) {
00510 *error = 1;
00511 }
00512 }
00513
00514 AST_LIST_INSERT_HEAD(working_list, acl, list);
00515 } else {
00516
00517 acl = current;
00518 }
00519
00520
00521 acl->acl = ast_append_ha(sense, stuff, acl->acl, error);
00522
00523 AST_LIST_UNLOCK(working_list);
00524 return;
00525 }
00526
00527
00528 list = ast_strdupa(stuff);
00529
00530 while ((tmp = strsep(&list, ","))) {
00531 struct ast_ha *named_ha;
00532 int already_included = 0;
00533
00534
00535 tmp = ast_skip_blanks(tmp);
00536
00537
00538 AST_LIST_TRAVERSE(working_list, current, list) {
00539 if (!strcasecmp(current->name, tmp)) {
00540
00541 ast_log(LOG_ERROR, "Named ACL '%s' is already included in the ast_acl container.", tmp);
00542 if (error) {
00543 *error = 1;
00544 }
00545 already_included = 1;
00546 break;
00547 }
00548 }
00549
00550 if (already_included) {
00551 continue;
00552 }
00553
00554 if (acl_new(&acl, tmp)) {
00555
00556 if (error) {
00557 *error = 1;
00558 }
00559 AST_LIST_UNLOCK(working_list);
00560 return;
00561 }
00562
00563
00564 named_ha = ast_named_acl_find(tmp, &acl->is_realtime, &acl->is_invalid);
00565
00566
00567 acl->acl = named_ha;
00568
00569
00570 if (named_acl_flag) {
00571 *named_acl_flag = 1;
00572 }
00573
00574
00575 AST_LIST_INSERT_TAIL(working_list, acl, list);
00576 }
00577
00578 AST_LIST_UNLOCK(working_list);
00579 }
00580
00581 int ast_acl_list_is_empty(struct ast_acl_list *acl_list)
00582 {
00583 struct ast_acl *head;
00584
00585 if (!acl_list) {
00586 return 1;
00587 }
00588
00589 AST_LIST_LOCK(acl_list);
00590 head = AST_LIST_FIRST(acl_list);
00591 AST_LIST_UNLOCK(acl_list);
00592
00593 if (head) {
00594 return 0;
00595 }
00596
00597 return 1;
00598 }
00599
00600 struct ast_ha *ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error)
00601 {
00602 struct ast_ha *ha;
00603 struct ast_ha *prev = NULL;
00604 struct ast_ha *ret;
00605 char *tmp, *list = ast_strdupa(stuff);
00606 char *address = NULL, *mask = NULL;
00607 int addr_is_v4;
00608 int allowing = strncasecmp(sense, "p", 1) ? AST_SENSE_DENY : AST_SENSE_ALLOW;
00609 const char *parsed_addr, *parsed_mask;
00610
00611 ret = path;
00612 while (path) {
00613 prev = path;
00614 path = path->next;
00615 }
00616
00617 while ((tmp = strsep(&list, ","))) {
00618 if (!(ha = ast_calloc(1, sizeof(*ha)))) {
00619 if (error) {
00620 *error = 1;
00621 }
00622 return ret;
00623 }
00624
00625 address = strsep(&tmp, "/");
00626 if (!address) {
00627 address = tmp;
00628 } else {
00629 mask = tmp;
00630 }
00631
00632 if (*address == '!') {
00633 ha->sense = (allowing == AST_SENSE_DENY) ? AST_SENSE_ALLOW : AST_SENSE_DENY;
00634 address++;
00635 } else {
00636 ha->sense = allowing;
00637 }
00638
00639 if (!ast_sockaddr_parse(&ha->addr, address, PARSE_PORT_FORBID)) {
00640 ast_log(LOG_WARNING, "Invalid IP address: %s\n", address);
00641 ast_free_ha(ha);
00642 if (error) {
00643 *error = 1;
00644 }
00645 return ret;
00646 }
00647
00648
00649
00650
00651 if (ast_sockaddr_ipv4_mapped(&ha->addr, &ha->addr)) {
00652 ast_log(LOG_NOTICE, "IPv4-mapped ACL network address specified. "
00653 "Converting to an IPv4 ACL network address.\n");
00654 }
00655
00656 addr_is_v4 = ast_sockaddr_is_ipv4(&ha->addr);
00657
00658 if (!mask) {
00659 parse_cidr_mask(&ha->netmask, addr_is_v4, addr_is_v4 ? "32" : "128");
00660 } else if (strchr(mask, ':') || strchr(mask, '.')) {
00661 int mask_is_v4;
00662
00663 if (!ast_sockaddr_parse(&ha->netmask, mask, PARSE_PORT_FORBID)) {
00664 ast_log(LOG_WARNING, "Invalid netmask: %s\n", mask);
00665 ast_free_ha(ha);
00666 if (error) {
00667 *error = 1;
00668 }
00669 return ret;
00670 }
00671
00672
00673
00674 if (ast_sockaddr_ipv4_mapped(&ha->netmask, &ha->netmask)) {
00675 ast_log(LOG_NOTICE, "IPv4-mapped ACL netmask specified. "
00676 "Converting to an IPv4 ACL netmask.\n");
00677 }
00678 mask_is_v4 = ast_sockaddr_is_ipv4(&ha->netmask);
00679 if (addr_is_v4 ^ mask_is_v4) {
00680 ast_log(LOG_WARNING, "Address and mask are not using same address scheme.\n");
00681 ast_free_ha(ha);
00682 if (error) {
00683 *error = 1;
00684 }
00685 return ret;
00686 }
00687 } else if (parse_cidr_mask(&ha->netmask, addr_is_v4, mask)) {
00688 ast_log(LOG_WARNING, "Invalid CIDR netmask: %s\n", mask);
00689 ast_free_ha(ha);
00690 if (error) {
00691 *error = 1;
00692 }
00693 return ret;
00694 }
00695
00696 if (apply_netmask(&ha->addr, &ha->netmask, &ha->addr)) {
00697
00698
00699
00700 char *failmask = ast_strdupa(ast_sockaddr_stringify(&ha->netmask));
00701 char *failaddr = ast_strdupa(ast_sockaddr_stringify(&ha->addr));
00702 ast_log(LOG_WARNING, "Unable to apply netmask %s to address %s\n", failmask, failaddr);
00703 ast_free_ha(ha);
00704 if (error) {
00705 *error = 1;
00706 }
00707 return ret;
00708 }
00709
00710 if (prev) {
00711 prev->next = ha;
00712 } else {
00713 ret = ha;
00714 }
00715 prev = ha;
00716
00717 parsed_addr = ast_strdupa(ast_sockaddr_stringify(&ha->addr));
00718 parsed_mask = ast_strdupa(ast_sockaddr_stringify(&ha->netmask));
00719
00720 ast_debug(3, "%s/%s sense %d appended to ACL\n", parsed_addr, parsed_mask, ha->sense);
00721 }
00722
00723 return ret;
00724 }
00725
00726 enum ast_acl_sense ast_apply_acl(struct ast_acl_list *acl_list, const struct ast_sockaddr *addr, const char *purpose)
00727 {
00728 struct ast_acl *acl;
00729
00730
00731 if (!acl_list) {
00732 return AST_SENSE_ALLOW;
00733 }
00734
00735 AST_LIST_LOCK(acl_list);
00736
00737 AST_LIST_TRAVERSE(acl_list, acl, list) {
00738 if (acl->is_invalid) {
00739
00740 ast_log(LOG_WARNING, "%sRejecting '%s' due to use of an invalid ACL '%s'.\n", purpose ? purpose : "", ast_sockaddr_stringify_addr(addr),
00741 ast_strlen_zero(acl->name) ? "(BASELINE)" : acl->name);
00742 AST_LIST_UNLOCK(acl_list);
00743 return AST_SENSE_DENY;
00744 }
00745
00746 if (acl->acl) {
00747 if (ast_apply_ha(acl->acl, addr) == AST_SENSE_DENY) {
00748 ast_log(LOG_NOTICE, "%sRejecting '%s' due to a failure to pass ACL '%s'\n", purpose ? purpose : "", ast_sockaddr_stringify_addr(addr),
00749 ast_strlen_zero(acl->name) ? "(BASELINE)" : acl->name);
00750 AST_LIST_UNLOCK(acl_list);
00751 return AST_SENSE_DENY;
00752 }
00753 }
00754 }
00755
00756 AST_LIST_UNLOCK(acl_list);
00757
00758 return AST_SENSE_ALLOW;
00759 }
00760
00761 enum ast_acl_sense ast_apply_ha(const struct ast_ha *ha, const struct ast_sockaddr *addr)
00762 {
00763
00764 enum ast_acl_sense res = AST_SENSE_ALLOW;
00765 const struct ast_ha *current_ha;
00766
00767 for (current_ha = ha; current_ha; current_ha = current_ha->next) {
00768 struct ast_sockaddr result;
00769 struct ast_sockaddr mapped_addr;
00770 const struct ast_sockaddr *addr_to_use;
00771 #if 0
00772 char iabuf[INET_ADDRSTRLEN];
00773 char iabuf2[INET_ADDRSTRLEN];
00774
00775 ast_copy_string(iabuf, ast_inet_ntoa(sin->sin_addr), sizeof(iabuf));
00776 ast_copy_string(iabuf2, ast_inet_ntoa(ha->netaddr), sizeof(iabuf2));
00777 ast_debug(1, "##### Testing %s with %s\n", iabuf, iabuf2);
00778 #endif
00779 if (ast_sockaddr_is_ipv4(&ha->addr)) {
00780 if (ast_sockaddr_is_ipv6(addr)) {
00781 if (ast_sockaddr_is_ipv4_mapped(addr)) {
00782
00783 if (!ast_sockaddr_ipv4_mapped(addr, &mapped_addr)) {
00784 ast_log(LOG_ERROR, "%s provided to ast_sockaddr_ipv4_mapped could not be converted. That shouldn't be possible.\n",
00785 ast_sockaddr_stringify(addr));
00786 continue;
00787 }
00788 addr_to_use = &mapped_addr;
00789 } else {
00790
00791 continue;
00792 }
00793 } else {
00794
00795 addr_to_use = addr;
00796 }
00797 } else {
00798 if (ast_sockaddr_is_ipv6(addr) && !ast_sockaddr_is_ipv4_mapped(addr)) {
00799 addr_to_use = addr;
00800 } else {
00801
00802 continue;
00803 }
00804 }
00805
00806
00807
00808 if (apply_netmask(addr_to_use, ¤t_ha->netmask, &result)) {
00809
00810 continue;
00811 }
00812 if (!ast_sockaddr_cmp_addr(&result, ¤t_ha->addr)) {
00813 res = current_ha->sense;
00814 }
00815 }
00816 return res;
00817 }
00818
00819 static int resolve_first(struct ast_sockaddr *addr, const char *name, int flag,
00820 int family)
00821 {
00822 struct ast_sockaddr *addrs;
00823 int addrs_cnt;
00824
00825 addrs_cnt = ast_sockaddr_resolve(&addrs, name, flag, family);
00826 if (addrs_cnt > 0) {
00827 if (addrs_cnt > 1) {
00828 ast_debug(1, "Multiple addresses. Using the first only\n");
00829 }
00830 ast_sockaddr_copy(addr, &addrs[0]);
00831 ast_free(addrs);
00832 } else {
00833 ast_log(LOG_WARNING, "Unable to lookup '%s'\n", name);
00834 return -1;
00835 }
00836
00837 return 0;
00838 }
00839
00840 int ast_get_ip_or_srv(struct ast_sockaddr *addr, const char *hostname, const char *service)
00841 {
00842 char srv[256];
00843 char host[256];
00844 int srv_ret = 0;
00845 int tportno;
00846
00847 if (service) {
00848 snprintf(srv, sizeof(srv), "%s.%s", service, hostname);
00849 if ((srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno, srv)) > 0) {
00850 hostname = host;
00851 }
00852 }
00853
00854 if (resolve_first(addr, hostname, PARSE_PORT_FORBID, addr->ss.ss_family) != 0) {
00855 return -1;
00856 }
00857
00858 if (srv_ret > 0) {
00859 ast_sockaddr_set_port(addr, tportno);
00860 }
00861
00862 return 0;
00863 }
00864
00865 struct dscp_codepoint {
00866 char *name;
00867 unsigned int space;
00868 };
00869
00870
00871
00872 static const struct dscp_codepoint dscp_pool1[] = {
00873 { "CS0", 0x00 },
00874 { "CS1", 0x08 },
00875 { "CS2", 0x10 },
00876 { "CS3", 0x18 },
00877 { "CS4", 0x20 },
00878 { "CS5", 0x28 },
00879 { "CS6", 0x30 },
00880 { "CS7", 0x38 },
00881 { "AF11", 0x0A },
00882 { "AF12", 0x0C },
00883 { "AF13", 0x0E },
00884 { "AF21", 0x12 },
00885 { "AF22", 0x14 },
00886 { "AF23", 0x16 },
00887 { "AF31", 0x1A },
00888 { "AF32", 0x1C },
00889 { "AF33", 0x1E },
00890 { "AF41", 0x22 },
00891 { "AF42", 0x24 },
00892 { "AF43", 0x26 },
00893 { "EF", 0x2E },
00894 };
00895
00896 int ast_str2cos(const char *value, unsigned int *cos)
00897 {
00898 int fval;
00899
00900 if (sscanf(value, "%30d", &fval) == 1) {
00901 if (fval < 8) {
00902 *cos = fval;
00903 return 0;
00904 }
00905 }
00906
00907 return -1;
00908 }
00909
00910 int ast_str2tos(const char *value, unsigned int *tos)
00911 {
00912 int fval;
00913 unsigned int x;
00914
00915 if (sscanf(value, "%30i", &fval) == 1) {
00916 *tos = fval & 0xFF;
00917 return 0;
00918 }
00919
00920 for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) {
00921 if (!strcasecmp(value, dscp_pool1[x].name)) {
00922 *tos = dscp_pool1[x].space << 2;
00923 return 0;
00924 }
00925 }
00926
00927 return -1;
00928 }
00929
00930 const char *ast_tos2str(unsigned int tos)
00931 {
00932 unsigned int x;
00933
00934 for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) {
00935 if (dscp_pool1[x].space == (tos >> 2)) {
00936 return dscp_pool1[x].name;
00937 }
00938 }
00939
00940 return "unknown";
00941 }
00942
00943 int ast_get_ip(struct ast_sockaddr *addr, const char *hostname)
00944 {
00945 return ast_get_ip_or_srv(addr, hostname, NULL);
00946 }
00947
00948 int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
00949 {
00950 int port;
00951 int s;
00952
00953 port = ast_sockaddr_port(us);
00954
00955 if ((s = socket(ast_sockaddr_is_ipv6(them) ? AF_INET6 : AF_INET,
00956 SOCK_DGRAM, 0)) < 0) {
00957 ast_log(LOG_ERROR, "Cannot create socket\n");
00958 return -1;
00959 }
00960
00961 if (ast_connect(s, them)) {
00962 ast_log(LOG_WARNING, "Cannot connect\n");
00963 close(s);
00964 return -1;
00965 }
00966 if (ast_getsockname(s, us)) {
00967
00968 ast_log(LOG_WARNING, "Cannot get socket name\n");
00969 close(s);
00970 return -1;
00971 }
00972 close(s);
00973
00974 {
00975 const char *them_addr = ast_strdupa(ast_sockaddr_stringify_addr(them));
00976 const char *us_addr = ast_strdupa(ast_sockaddr_stringify_addr(us));
00977
00978 ast_debug(3, "For destination '%s', our source address is '%s'.\n",
00979 them_addr, us_addr);
00980 }
00981
00982 ast_sockaddr_set_port(us, port);
00983
00984 return 0;
00985 }
00986
00987 int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr, int family)
00988 {
00989 char ourhost[MAXHOSTNAMELEN] = "";
00990 struct ast_sockaddr root;
00991 int res, port = ast_sockaddr_port(ourip);
00992
00993
00994 if (!ast_sockaddr_is_any(bindaddr)) {
00995 ast_sockaddr_copy(ourip, bindaddr);
00996 ast_debug(3, "Attached to given IP address\n");
00997 return 0;
00998 }
00999
01000 if (gethostname(ourhost, sizeof(ourhost) - 1)) {
01001 ast_log(LOG_WARNING, "Unable to get hostname\n");
01002 } else {
01003 if (resolve_first(ourip, ourhost, PARSE_PORT_FORBID, family) == 0) {
01004
01005 ast_sockaddr_set_port(ourip, port);
01006 return 0;
01007 }
01008 }
01009 ast_debug(3, "Trying to check A.ROOT-SERVERS.NET and get our IP address for that connection\n");
01010
01011 if (!resolve_first(&root, "A.ROOT-SERVERS.NET", PARSE_PORT_FORBID, 0) &&
01012 !ast_ouraddrfor(&root, ourip)) {
01013
01014 ast_sockaddr_set_port(ourip, port);
01015 return 0;
01016 }
01017 res = get_local_address(ourip);
01018 ast_sockaddr_set_port(ourip, port);
01019 return res;
01020 }
01021