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 #include "asterisk.h"
00027
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 291264 $")
00029
00030 #include "asterisk/network.h"
00031
00032 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__Darwin__)
00033 #include <fcntl.h>
00034 #include <net/route.h>
00035 #endif
00036
00037 #if defined(SOLARIS)
00038 #include <sys/sockio.h>
00039 #include <net/if.h>
00040 #elif defined(HAVE_GETIFADDRS)
00041 #include <ifaddrs.h>
00042 #endif
00043
00044 #include "asterisk/acl.h"
00045 #include "asterisk/channel.h"
00046 #include "asterisk/utils.h"
00047 #include "asterisk/lock.h"
00048 #include "asterisk/srv.h"
00049
00050 #if (!defined(SOLARIS) && !defined(HAVE_GETIFADDRS))
00051 static int get_local_address(struct in_addr *ourip)
00052 {
00053 return -1;
00054 }
00055 #else
00056 static void score_address(const struct sockaddr_in *sin, struct in_addr *best_addr, int *best_score)
00057 {
00058 const char *address;
00059 int score;
00060
00061 address = ast_inet_ntoa(sin->sin_addr);
00062
00063
00064 if (address[0] == '0') {
00065 score = -25;
00066
00067 } else if (strncmp(address, "127", 3) == 0) {
00068 score = -20;
00069
00070 } else if (strncmp(address, "10.", 3) == 0) {
00071 score = -5;
00072
00073 } else if (strncmp(address, "172", 3) == 0) {
00074
00075 if (address[4] == '1' && address[5] >= '6' && address[6] == '.') {
00076 score = -5;
00077
00078 } else if (address[4] == '2' && address[6] == '.') {
00079 score = -5;
00080
00081 } else if (address[4] == '3' && (address[5] == '0' || address[5] == '1')) {
00082 score = -5;
00083
00084 } else {
00085 score = 0;
00086 }
00087
00088 } else if (strncmp(address, "198.1", 5) == 0 && address[5] >= '8' && address[6] == '.') {
00089 score = -10;
00090
00091 } else if (strncmp(address, "192.168", 7) == 0) {
00092 score = -5;
00093
00094 } else if (strncmp(address, "169.254", 7) == 0) {
00095
00096
00097
00098
00099
00100 score = -10;
00101
00102 } else if (strncmp(address, "192.0.2.", 8) == 0) {
00103 score = -15;
00104
00105 } else {
00106 score = 0;
00107 }
00108
00109 if (score > *best_score) {
00110 *best_score = score;
00111 memcpy(best_addr, &sin->sin_addr, sizeof(*best_addr));
00112 }
00113 }
00114
00115 static int get_local_address(struct in_addr *ourip)
00116 {
00117 int s, res = -1;
00118 #ifdef SOLARIS
00119 struct lifreq *ifr = NULL;
00120 struct lifnum ifn;
00121 struct lifconf ifc;
00122 struct sockaddr_in *sa;
00123 char *buf = NULL;
00124 int bufsz, x;
00125 #endif
00126 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
00127 struct ifaddrs *ifap, *ifaphead;
00128 int rtnerr;
00129 const struct sockaddr_in *sin;
00130 #endif
00131 struct in_addr best_addr;
00132 int best_score = -100;
00133 memset(&best_addr, 0, sizeof(best_addr));
00134
00135 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
00136 rtnerr = getifaddrs(&ifaphead);
00137 if (rtnerr) {
00138 perror(NULL);
00139 return -1;
00140 }
00141 #endif
00142
00143 s = socket(AF_INET, SOCK_STREAM, 0);
00144
00145 if (s > 0) {
00146 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
00147 for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) {
00148
00149 if (ifap->ifa_addr && ifap->ifa_addr->sa_family == AF_INET) {
00150 sin = (const struct sockaddr_in *) ifap->ifa_addr;
00151 score_address(sin, &best_addr, &best_score);
00152 res = 0;
00153
00154 if (best_score == 0) {
00155 break;
00156 }
00157 }
00158 }
00159 #endif
00160
00161
00162 #ifdef SOLARIS
00163
00164 ifn.lifn_family = AF_INET;
00165 ifn.lifn_flags = 0;
00166 ifn.lifn_count = 0;
00167 if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) {
00168 close(s);
00169 return -1;
00170 }
00171
00172 bufsz = ifn.lifn_count * sizeof(struct lifreq);
00173 if (!(buf = malloc(bufsz))) {
00174 close(s);
00175 return -1;
00176 }
00177 memset(buf, 0, bufsz);
00178
00179
00180 ifc.lifc_len = bufsz;
00181 ifc.lifc_buf = buf;
00182 ifc.lifc_family = AF_INET;
00183 ifc.lifc_flags = 0;
00184 if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) {
00185 close(s);
00186 free(buf);
00187 return -1;
00188 }
00189
00190 for (ifr = ifc.lifc_req, x = 0; x < ifn.lifn_count; ifr++, x++) {
00191 sa = (struct sockaddr_in *)&(ifr->lifr_addr);
00192 score_address(sa, &best_addr, &best_score);
00193 res = 0;
00194
00195 if (best_score == 0) {
00196 break;
00197 }
00198 }
00199
00200 free(buf);
00201 #endif
00202
00203 close(s);
00204 }
00205 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
00206 freeifaddrs(ifaphead);
00207 #endif
00208
00209 if (res == 0 && ourip) {
00210 memcpy(ourip, &best_addr, sizeof(*ourip));
00211 }
00212 return res;
00213 }
00214 #endif
00215
00216
00217 void ast_free_ha(struct ast_ha *ha)
00218 {
00219 struct ast_ha *hal;
00220 while (ha) {
00221 hal = ha;
00222 ha = ha->next;
00223 ast_free(hal);
00224 }
00225 }
00226
00227
00228 void ast_copy_ha(const struct ast_ha *from, struct ast_ha *to)
00229 {
00230 memcpy(&to->netaddr, &from->netaddr, sizeof(from->netaddr));
00231 memcpy(&to->netmask, &from->netmask, sizeof(from->netmask));
00232 to->sense = from->sense;
00233 }
00234
00235
00236 static struct ast_ha *ast_duplicate_ha(struct ast_ha *original)
00237 {
00238 struct ast_ha *new_ha;
00239
00240 if ((new_ha = ast_malloc(sizeof(*new_ha)))) {
00241
00242 ast_copy_ha(original, new_ha);
00243 }
00244
00245 return new_ha;
00246 }
00247
00248
00249
00250 struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original)
00251 {
00252 struct ast_ha *start = original;
00253 struct ast_ha *ret = NULL;
00254 struct ast_ha *current, *prev = NULL;
00255
00256 while (start) {
00257 current = ast_duplicate_ha(start);
00258 if (prev) {
00259 prev->next = current;
00260 }
00261
00262 if (!ret) {
00263 ret = current;
00264 }
00265
00266 start = start->next;
00267 prev = current;
00268 }
00269 return ret;
00270 }
00271
00272 struct ast_ha *ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error)
00273 {
00274 struct ast_ha *ha;
00275 char *nm;
00276 struct ast_ha *prev = NULL;
00277 struct ast_ha *ret;
00278 int x;
00279 char *tmp = ast_strdupa(stuff);
00280
00281 ret = path;
00282 while (path) {
00283 prev = path;
00284 path = path->next;
00285 }
00286
00287 if (!(ha = ast_malloc(sizeof(*ha)))) {
00288 return ret;
00289 }
00290
00291 if (!(nm = strchr(tmp, '/'))) {
00292
00293
00294 ha->netmask.s_addr = htonl(0xFFFFFFFF);
00295 } else {
00296 *nm = '\0';
00297 nm++;
00298
00299 if (!strchr(nm, '.')) {
00300 if ((sscanf(nm, "%30d", &x) == 1) && (x >= 0) && (x <= 32)) {
00301 if (x == 0) {
00302
00303
00304
00305 ha->netmask.s_addr = 0;
00306 } else {
00307 ha->netmask.s_addr = htonl(0xFFFFFFFF << (32 - x));
00308 }
00309 } else {
00310 ast_log(LOG_WARNING, "Invalid CIDR in %s\n", stuff);
00311 ast_free(ha);
00312 if (error) {
00313 *error = 1;
00314 }
00315 return ret;
00316 }
00317 } else if (!inet_aton(nm, &ha->netmask)) {
00318 ast_log(LOG_WARNING, "Invalid mask in %s\n", stuff);
00319 ast_free(ha);
00320 if (error) {
00321 *error = 1;
00322 }
00323 return ret;
00324 }
00325 }
00326
00327 if (!inet_aton(tmp, &ha->netaddr)) {
00328 ast_log(LOG_WARNING, "Invalid IP address in %s\n", stuff);
00329 ast_free(ha);
00330 if (error) {
00331 *error = 1;
00332 }
00333 return ret;
00334 }
00335
00336 ha->netaddr.s_addr &= ha->netmask.s_addr;
00337
00338 ha->sense = strncasecmp(sense, "p", 1) ? AST_SENSE_DENY : AST_SENSE_ALLOW;
00339
00340 ha->next = NULL;
00341 if (prev) {
00342 prev->next = ha;
00343 } else {
00344 ret = ha;
00345 }
00346
00347 ast_debug(1, "%s/%s sense %d appended to acl for peer\n", ast_strdupa(ast_inet_ntoa(ha->netaddr)), ast_strdupa(ast_inet_ntoa(ha->netmask)), ha->sense);
00348
00349 return ret;
00350 }
00351
00352 int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
00353 {
00354
00355 int res = AST_SENSE_ALLOW;
00356 while (ha) {
00357 #if 0
00358 char iabuf[INET_ADDRSTRLEN];
00359 char iabuf2[INET_ADDRSTRLEN];
00360
00361 ast_copy_string(iabuf, ast_inet_ntoa(sin->sin_addr), sizeof(iabuf));
00362 ast_copy_string(iabuf2, ast_inet_ntoa(ha->netaddr), sizeof(iabuf2));
00363 ast_debug(1, "##### Testing %s with %s\n", iabuf, iabuf2);
00364 #endif
00365
00366
00367 if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == ha->netaddr.s_addr) {
00368 res = ha->sense;
00369 }
00370 ha = ha->next;
00371 }
00372 return res;
00373 }
00374
00375 int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *service)
00376 {
00377 struct hostent *hp;
00378 struct ast_hostent ahp;
00379 char srv[256];
00380 char host[256];
00381 int tportno = ntohs(sin->sin_port);
00382 if (service) {
00383 snprintf(srv, sizeof(srv), "%s.%s", service, value);
00384 if (ast_get_srv(NULL, host, sizeof(host), &tportno, srv) > 0) {
00385 sin->sin_port = htons(tportno);
00386 value = host;
00387 }
00388 }
00389 if ((hp = ast_gethostbyname(value, &ahp))) {
00390 sin->sin_family = hp->h_addrtype;
00391 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
00392 } else {
00393 ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value);
00394 return -1;
00395 }
00396 return 0;
00397 }
00398
00399 struct dscp_codepoint {
00400 char *name;
00401 unsigned int space;
00402 };
00403
00404
00405
00406 static const struct dscp_codepoint dscp_pool1[] = {
00407 { "CS0", 0x00 },
00408 { "CS1", 0x08 },
00409 { "CS2", 0x10 },
00410 { "CS3", 0x18 },
00411 { "CS4", 0x20 },
00412 { "CS5", 0x28 },
00413 { "CS6", 0x30 },
00414 { "CS7", 0x38 },
00415 { "AF11", 0x0A },
00416 { "AF12", 0x0C },
00417 { "AF13", 0x0E },
00418 { "AF21", 0x12 },
00419 { "AF22", 0x14 },
00420 { "AF23", 0x16 },
00421 { "AF31", 0x1A },
00422 { "AF32", 0x1C },
00423 { "AF33", 0x1E },
00424 { "AF41", 0x22 },
00425 { "AF42", 0x24 },
00426 { "AF43", 0x26 },
00427 { "EF", 0x2E },
00428 };
00429
00430 int ast_str2cos(const char *value, unsigned int *cos)
00431 {
00432 int fval;
00433
00434 if (sscanf(value, "%30d", &fval) == 1) {
00435 if (fval < 8) {
00436 *cos = fval;
00437 return 0;
00438 }
00439 }
00440
00441 return -1;
00442 }
00443
00444 int ast_str2tos(const char *value, unsigned int *tos)
00445 {
00446 int fval;
00447 unsigned int x;
00448
00449 if (sscanf(value, "%30i", &fval) == 1) {
00450 *tos = fval & 0xFF;
00451 return 0;
00452 }
00453
00454 for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) {
00455 if (!strcasecmp(value, dscp_pool1[x].name)) {
00456 *tos = dscp_pool1[x].space << 2;
00457 return 0;
00458 }
00459 }
00460
00461 return -1;
00462 }
00463
00464 const char *ast_tos2str(unsigned int tos)
00465 {
00466 unsigned int x;
00467
00468 for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) {
00469 if (dscp_pool1[x].space == (tos >> 2)) {
00470 return dscp_pool1[x].name;
00471 }
00472 }
00473
00474 return "unknown";
00475 }
00476
00477 int ast_get_ip(struct sockaddr_in *sin, const char *value)
00478 {
00479 return ast_get_ip_or_srv(sin, value, NULL);
00480 }
00481
00482 int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
00483 {
00484 int s;
00485 struct sockaddr_in sin;
00486 socklen_t slen;
00487
00488 if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
00489 ast_log(LOG_ERROR, "Cannot create socket\n");
00490 return -1;
00491 }
00492 sin.sin_family = AF_INET;
00493 sin.sin_port = htons(5060);
00494 sin.sin_addr = *them;
00495 if (connect(s, (struct sockaddr *)&sin, sizeof(sin))) {
00496 ast_log(LOG_WARNING, "Cannot connect\n");
00497 close(s);
00498 return -1;
00499 }
00500 slen = sizeof(sin);
00501 if (getsockname(s, (struct sockaddr *)&sin, &slen)) {
00502 ast_log(LOG_WARNING, "Cannot get socket name\n");
00503 close(s);
00504 return -1;
00505 }
00506 close(s);
00507 ast_debug(3, "Found IP address for this socket\n");
00508 *us = sin.sin_addr;
00509 return 0;
00510 }
00511
00512 int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr)
00513 {
00514 char ourhost[MAXHOSTNAMELEN] = "";
00515 struct ast_hostent ahp;
00516 struct hostent *hp;
00517 struct in_addr saddr;
00518
00519
00520 if (ntohl(bindaddr.sin_addr.s_addr)) {
00521 memcpy(ourip, &bindaddr.sin_addr, sizeof(*ourip));
00522 ast_debug(3, "Attached to given IP address\n");
00523 return 0;
00524 }
00525
00526 if (gethostname(ourhost, sizeof(ourhost) - 1)) {
00527 ast_log(LOG_WARNING, "Unable to get hostname\n");
00528 } else {
00529 if ((hp = ast_gethostbyname(ourhost, &ahp))) {
00530 memcpy(ourip, hp->h_addr, sizeof(*ourip));
00531 ast_debug(3, "Found one IP address based on local hostname %s.\n", ourhost);
00532 return 0;
00533 }
00534 }
00535 ast_debug(3, "Trying to check A.ROOT-SERVERS.NET and get our IP address for that connection\n");
00536
00537 if (inet_aton("198.41.0.4", &saddr) && !ast_ouraddrfor(&saddr, ourip)) {
00538 return 0;
00539 }
00540 return get_local_address(ourip);
00541 }
00542