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: 292188 $")
00029
00030 #include "asterisk/config.h"
00031 #include "asterisk/netsock2.h"
00032 #include "asterisk/utils.h"
00033 #include "asterisk/threadstorage.h"
00034
00035 int ast_sockaddr_ipv4_mapped(const struct ast_sockaddr *addr, struct ast_sockaddr *ast_mapped)
00036 {
00037 const struct sockaddr_in6 *sin6;
00038 struct sockaddr_in sin4;
00039
00040 if (!ast_sockaddr_is_ipv6(addr)) {
00041 return 0;
00042 }
00043
00044 if (!ast_sockaddr_is_ipv4_mapped(addr)) {
00045 return 0;
00046 }
00047
00048 sin6 = (const struct sockaddr_in6*)&addr->ss;
00049
00050 memset(&sin4, 0, sizeof(sin4));
00051 sin4.sin_family = AF_INET;
00052 sin4.sin_port = sin6->sin6_port;
00053 sin4.sin_addr.s_addr = ((uint32_t *)&sin6->sin6_addr)[3];
00054
00055 ast_sockaddr_from_sin(ast_mapped, &sin4);
00056
00057 return 1;
00058 }
00059
00060
00061 AST_THREADSTORAGE(ast_sockaddr_stringify_buf);
00062
00063 char *ast_sockaddr_stringify_fmt(const struct ast_sockaddr *sa, int format)
00064 {
00065 struct ast_sockaddr sa_ipv4;
00066 const struct ast_sockaddr *sa_tmp;
00067 char host[NI_MAXHOST];
00068 char port[NI_MAXSERV];
00069 struct ast_str *str;
00070 int e;
00071 static const size_t size = sizeof(host) - 1 + sizeof(port) - 1 + 4;
00072
00073
00074 if (ast_sockaddr_isnull(sa)) {
00075 return "(null)";
00076 }
00077
00078 if (!(str = ast_str_thread_get(&ast_sockaddr_stringify_buf, size))) {
00079 return "";
00080 }
00081
00082 if (ast_sockaddr_ipv4_mapped(sa, &sa_ipv4)) {
00083 sa_tmp = &sa_ipv4;
00084 } else {
00085 sa_tmp = sa;
00086 }
00087
00088 if ((e = getnameinfo((struct sockaddr *)&sa_tmp->ss, sa->len,
00089 format & AST_SOCKADDR_STR_ADDR ? host : NULL,
00090 format & AST_SOCKADDR_STR_ADDR ? sizeof(host) : 0,
00091 format & AST_SOCKADDR_STR_PORT ? port : 0,
00092 format & AST_SOCKADDR_STR_PORT ? sizeof(port): 0,
00093 NI_NUMERICHOST | NI_NUMERICSERV))) {
00094 ast_log(LOG_ERROR, "getnameinfo(): %s\n", gai_strerror(e));
00095 return "";
00096 }
00097
00098 switch (format) {
00099 case AST_SOCKADDR_STR_DEFAULT:
00100 ast_str_set(&str, 0, sa_tmp->ss.ss_family == AF_INET6 ?
00101 "[%s]:%s" : "%s:%s", host, port);
00102 break;
00103 case AST_SOCKADDR_STR_ADDR:
00104 ast_str_set(&str, 0, "%s", host);
00105 break;
00106 case AST_SOCKADDR_STR_HOST:
00107 ast_str_set(&str, 0,
00108 sa_tmp->ss.ss_family == AF_INET6 ? "[%s]" : "%s", host);
00109 break;
00110 case AST_SOCKADDR_STR_PORT:
00111 ast_str_set(&str, 0, "%s", port);
00112 break;
00113 default:
00114 ast_log(LOG_ERROR, "Invalid format\n");
00115 return "";
00116 }
00117
00118 return ast_str_buffer(str);
00119 }
00120
00121 int ast_sockaddr_split_hostport(char *str, char **host, char **port, int flags)
00122 {
00123 char *s = str;
00124
00125 ast_debug(5, "Splitting '%s' gives...\n", str);
00126 *host = NULL;
00127 *port = NULL;
00128 if (*s == '[') {
00129 *host = ++s;
00130 for (; *s && *s != ']'; ++s) {
00131 }
00132 if (*s == ']') {
00133 *s++ = '\0';
00134 }
00135 if (*s == ':') {
00136 *port = s + 1;
00137 }
00138 } else {
00139 *host = s;
00140 for (; *s; ++s) {
00141 if (*s == ':') {
00142 if (*port) {
00143 *port = NULL;
00144 break;
00145 } else {
00146 *port = s;
00147 }
00148 }
00149 }
00150 if (*port) {
00151 **port = '\0';
00152 ++*port;
00153 }
00154 }
00155 ast_debug(5, "...host '%s' and port '%s'.\n", *host, *port);
00156
00157 switch (flags & PARSE_PORT_MASK) {
00158 case PARSE_PORT_IGNORE:
00159 *port = NULL;
00160 break;
00161 case PARSE_PORT_REQUIRE:
00162 if (*port == NULL) {
00163 ast_log(LOG_WARNING, "missing port\n");
00164 return 0;
00165 }
00166 break;
00167 case PARSE_PORT_FORBID:
00168 if (*port != NULL) {
00169 ast_log(LOG_WARNING, "port disallowed\n");
00170 return 0;
00171 }
00172 break;
00173 }
00174
00175 return 1;
00176 }
00177
00178
00179
00180 int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
00181 {
00182 struct addrinfo hints;
00183 struct addrinfo *res;
00184 char *s;
00185 char *host;
00186 char *port;
00187 int e;
00188
00189 s = ast_strdupa(str);
00190 if (!ast_sockaddr_split_hostport(s, &host, &port, flags)) {
00191 return 0;
00192 }
00193
00194 memset(&hints, 0, sizeof(hints));
00195
00196 hints.ai_socktype = SOCK_DGRAM;
00197
00198 #ifdef AI_NUMERICSERV
00199 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
00200 #else
00201 hints.ai_flags = AI_NUMERICHOST;
00202 #endif
00203 if ((e = getaddrinfo(host, port, &hints, &res))) {
00204 if (e != EAI_NONAME) {
00205 ast_log(LOG_ERROR, "getaddrinfo(\"%s\", \"%s\", ...): %s\n",
00206 host, S_OR(port, "(null)"), gai_strerror(e));
00207 }
00208 return 0;
00209 }
00210
00211
00212
00213
00214
00215 if (res->ai_next != NULL) {
00216 ast_log(LOG_WARNING, "getaddrinfo() returned multiple "
00217 "addresses. Ignoring all but the first.\n");
00218 }
00219
00220 addr->len = res->ai_addrlen;
00221 memcpy(&addr->ss, res->ai_addr, addr->len);
00222
00223 freeaddrinfo(res);
00224
00225 return 1;
00226 }
00227
00228 int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str,
00229 int flags, int family)
00230 {
00231 struct addrinfo hints, *res, *ai;
00232 char *s, *host, *port;
00233 int e, i, res_cnt;
00234
00235 s = ast_strdupa(str);
00236 if (!ast_sockaddr_split_hostport(s, &host, &port, flags)) {
00237 return 0;
00238 }
00239
00240 memset(&hints, 0, sizeof(hints));
00241 hints.ai_family = family;
00242 hints.ai_socktype = SOCK_DGRAM;
00243
00244 if ((e = getaddrinfo(host, port, &hints, &res))) {
00245 ast_log(LOG_ERROR, "getaddrinfo(\"%s\", \"%s\", ...): %s\n",
00246 host, S_OR(port, "(null)"), gai_strerror(e));
00247 return 0;
00248 }
00249
00250 res_cnt = 0;
00251 for (ai = res; ai; ai = ai->ai_next) {
00252 res_cnt++;
00253 }
00254
00255 if ((*addrs = ast_malloc(res_cnt * sizeof(struct ast_sockaddr))) == NULL) {
00256 res_cnt = 0;
00257 goto cleanup;
00258 }
00259
00260 i = 0;
00261 for (ai = res; ai; ai = ai->ai_next) {
00262 (*addrs)[i].len = ai->ai_addrlen;
00263 memcpy(&(*addrs)[i].ss, ai->ai_addr, ai->ai_addrlen);
00264 ++i;
00265 }
00266
00267 cleanup:
00268 freeaddrinfo(res);
00269 return res_cnt;
00270 }
00271
00272 int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
00273 {
00274 const struct ast_sockaddr *a_tmp, *b_tmp;
00275 struct ast_sockaddr ipv4_mapped;
00276
00277 a_tmp = a;
00278 b_tmp = b;
00279
00280 if (a_tmp->len != b_tmp->len) {
00281 if (ast_sockaddr_ipv4_mapped(a, &ipv4_mapped)) {
00282 a_tmp = &ipv4_mapped;
00283 } else if (ast_sockaddr_ipv4_mapped(b, &ipv4_mapped)) {
00284 b_tmp = &ipv4_mapped;
00285 }
00286 }
00287
00288 if (a_tmp->len < b_tmp->len) {
00289 return -1;
00290 } else if (a_tmp->len > b_tmp->len) {
00291 return 1;
00292 }
00293
00294 return memcmp(&a_tmp->ss, &b_tmp->ss, a_tmp->len);
00295 }
00296
00297 int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
00298 {
00299 const struct ast_sockaddr *a_tmp, *b_tmp;
00300 struct ast_sockaddr ipv4_mapped;
00301 const struct in_addr *ip4a, *ip4b;
00302 const struct in6_addr *ip6a, *ip6b;
00303 int ret = -1;
00304
00305 a_tmp = a;
00306 b_tmp = b;
00307
00308 if (a_tmp->len != b_tmp->len) {
00309 if (ast_sockaddr_ipv4_mapped(a, &ipv4_mapped)) {
00310 a_tmp = &ipv4_mapped;
00311 } else if (ast_sockaddr_ipv4_mapped(b, &ipv4_mapped)) {
00312 b_tmp = &ipv4_mapped;
00313 }
00314 }
00315
00316 if (a->len < b->len) {
00317 ret = -1;
00318 } else if (a->len > b->len) {
00319 ret = 1;
00320 }
00321
00322 switch (a_tmp->ss.ss_family) {
00323 case AF_INET:
00324 ip4a = &((const struct sockaddr_in*)&a_tmp->ss)->sin_addr;
00325 ip4b = &((const struct sockaddr_in*)&b_tmp->ss)->sin_addr;
00326 ret = memcmp(ip4a, ip4b, sizeof(*ip4a));
00327 break;
00328 case AF_INET6:
00329 ip6a = &((const struct sockaddr_in6*)&a_tmp->ss)->sin6_addr;
00330 ip6b = &((const struct sockaddr_in6*)&b_tmp->ss)->sin6_addr;
00331 ret = memcmp(ip6a, ip6b, sizeof(*ip6a));
00332 break;
00333 }
00334 return ret;
00335 }
00336
00337 uint16_t _ast_sockaddr_port(const struct ast_sockaddr *addr, const char *file, int line, const char *func)
00338 {
00339 if (addr->ss.ss_family == AF_INET &&
00340 addr->len == sizeof(struct sockaddr_in)) {
00341 return ntohs(((struct sockaddr_in *)&addr->ss)->sin_port);
00342 } else if (addr->ss.ss_family == AF_INET6 &&
00343 addr->len == sizeof(struct sockaddr_in6)) {
00344 return ntohs(((struct sockaddr_in6 *)&addr->ss)->sin6_port);
00345 }
00346 if (option_debug >= 1) {
00347 ast_log(__LOG_DEBUG, file, line, func, "Not an IPv4 nor IPv6 address, cannot get port.\n");
00348 }
00349 return 0;
00350 }
00351
00352 void _ast_sockaddr_set_port(struct ast_sockaddr *addr, uint16_t port, const char *file, int line, const char *func)
00353 {
00354 if (addr->ss.ss_family == AF_INET &&
00355 addr->len == sizeof(struct sockaddr_in)) {
00356 ((struct sockaddr_in *)&addr->ss)->sin_port = htons(port);
00357 } else if (addr->ss.ss_family == AF_INET6 &&
00358 addr->len == sizeof(struct sockaddr_in6)) {
00359 ((struct sockaddr_in6 *)&addr->ss)->sin6_port = htons(port);
00360 } else if (option_debug >= 1) {
00361 ast_log(__LOG_DEBUG, file, line, func,
00362 "Not an IPv4 nor IPv6 address, cannot set port.\n");
00363 }
00364 }
00365
00366 uint32_t ast_sockaddr_ipv4(const struct ast_sockaddr *addr)
00367 {
00368 const struct sockaddr_in *sin = (struct sockaddr_in *)&addr->ss;
00369 return ntohl(sin->sin_addr.s_addr);
00370 }
00371
00372 int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
00373 {
00374 return addr->ss.ss_family == AF_INET &&
00375 addr->len == sizeof(struct sockaddr_in);
00376 }
00377
00378 int ast_sockaddr_is_ipv4_mapped(const struct ast_sockaddr *addr)
00379 {
00380 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr->ss;
00381 return addr->len && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr);
00382 }
00383
00384 int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
00385 {
00386 return addr->ss.ss_family == AF_INET6 &&
00387 addr->len == sizeof(struct sockaddr_in6);
00388 }
00389
00390 int ast_sockaddr_is_any(const struct ast_sockaddr *addr)
00391 {
00392 union {
00393 struct sockaddr_storage ss;
00394 struct sockaddr_in sin;
00395 struct sockaddr_in6 sin6;
00396 } tmp_addr = {
00397 .ss = addr->ss,
00398 };
00399
00400 return (ast_sockaddr_is_ipv4(addr) && (tmp_addr.sin.sin_addr.s_addr == INADDR_ANY)) ||
00401 (ast_sockaddr_is_ipv6(addr) && IN6_IS_ADDR_UNSPECIFIED(&tmp_addr.sin6.sin6_addr));
00402 }
00403
00404 int ast_sockaddr_hash(const struct ast_sockaddr *addr)
00405 {
00406
00407
00408
00409
00410 switch (addr->ss.ss_family) {
00411 case AF_INET:
00412 return ((const struct sockaddr_in *)&addr->ss)->sin_addr.s_addr;
00413 case AF_INET6:
00414 return ((uint32_t *)&((const struct sockaddr_in6 *)&addr->ss)->sin6_addr)[3];
00415 default:
00416 ast_log(LOG_ERROR, "Unknown address family '%d'.\n",
00417 addr->ss.ss_family);
00418 return 0;
00419 }
00420 }
00421
00422 int ast_accept(int sockfd, struct ast_sockaddr *addr)
00423 {
00424 addr->len = sizeof(addr->ss);
00425 return accept(sockfd, (struct sockaddr *)&addr->ss, &addr->len);
00426 }
00427
00428 int ast_bind(int sockfd, const struct ast_sockaddr *addr)
00429 {
00430 return bind(sockfd, (const struct sockaddr *)&addr->ss, addr->len);
00431 }
00432
00433 int ast_connect(int sockfd, const struct ast_sockaddr *addr)
00434 {
00435 return connect(sockfd, (const struct sockaddr *)&addr->ss, addr->len);
00436 }
00437
00438 int ast_getsockname(int sockfd, struct ast_sockaddr *addr)
00439 {
00440 addr->len = sizeof(addr->ss);
00441 return getsockname(sockfd, (struct sockaddr *)&addr->ss, &addr->len);
00442 }
00443
00444 ssize_t ast_recvfrom(int sockfd, void *buf, size_t len, int flags,
00445 struct ast_sockaddr *src_addr)
00446 {
00447 src_addr->len = sizeof(src_addr->ss);
00448 return recvfrom(sockfd, buf, len, flags,
00449 (struct sockaddr *)&src_addr->ss, &src_addr->len);
00450 }
00451
00452 ssize_t ast_sendto(int sockfd, const void *buf, size_t len, int flags,
00453 const struct ast_sockaddr *dest_addr)
00454 {
00455 return sendto(sockfd, buf, len, flags,
00456 (const struct sockaddr *)&dest_addr->ss, dest_addr->len);
00457 }
00458
00459 int ast_set_qos(int sockfd, int tos, int cos, const char *desc)
00460 {
00461 int res = 0;
00462 int set_tos;
00463 int set_tclass;
00464 struct ast_sockaddr addr;
00465
00466
00467 set_tclass = !ast_getsockname(sockfd, &addr) && ast_sockaddr_is_ipv6(&addr) ? 1 : 0;
00468
00469
00470 set_tos = (!set_tclass || (set_tclass && ast_sockaddr_is_any(&addr))) ? 1 : 0;
00471
00472 if (set_tos) {
00473 if ((res = setsockopt(sockfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) {
00474 ast_log(LOG_WARNING, "Unable to set %s DSCP TOS value to %d (may be you have no "
00475 "root privileges): %s\n", desc, tos, strerror(errno));
00476 } else if (tos) {
00477 ast_verb(2, "Using %s TOS bits %d\n", desc, tos);
00478 }
00479 }
00480
00481 #if defined(IPV6_TCLASS) && defined(IPPROTO_IPV6)
00482 if (set_tclass) {
00483 if (!ast_getsockname(sockfd, &addr) && ast_sockaddr_is_ipv6(&addr)) {
00484 if ((res = setsockopt(sockfd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)))) {
00485 ast_log(LOG_WARNING, "Unable to set %s DSCP TCLASS field to %d (may be you have no "
00486 "root privileges): %s\n", desc, tos, strerror(errno));
00487 } else if (tos) {
00488 ast_verb(2, "Using %s TOS bits %d in TCLASS field.\n", desc, tos);
00489 }
00490 }
00491 }
00492 #endif
00493
00494 #ifdef linux
00495 if (setsockopt(sockfd, SOL_SOCKET, SO_PRIORITY, &cos, sizeof(cos))) {
00496 ast_log(LOG_WARNING, "Unable to set %s CoS to %d: %s\n", desc, cos,
00497 strerror(errno));
00498 } else if (cos) {
00499 ast_verb(2, "Using %s CoS mark %d\n", desc, cos);
00500 }
00501 #endif
00502
00503 return res;
00504 }
00505
00506 int _ast_sockaddr_to_sin(const struct ast_sockaddr *addr,
00507 struct sockaddr_in *sin, const char *file, int line, const char *func)
00508 {
00509 if (ast_sockaddr_isnull(addr)) {
00510 memset(sin, 0, sizeof(*sin));
00511 return 1;
00512 }
00513
00514 if (addr->len != sizeof(*sin)) {
00515 ast_log(__LOG_ERROR, file, line, func, "Bad address cast to IPv4\n");
00516 return 0;
00517 }
00518
00519 if (addr->ss.ss_family != AF_INET && option_debug >= 1) {
00520 ast_log(__LOG_DEBUG, file, line, func, "Address family is not AF_INET\n");
00521 }
00522
00523 *sin = *(struct sockaddr_in *)&addr->ss;
00524 return 1;
00525 }
00526
00527 void _ast_sockaddr_from_sin(struct ast_sockaddr *addr, const struct sockaddr_in *sin,
00528 const char *file, int line, const char *func)
00529 {
00530 memcpy(&addr->ss, sin, sizeof(*sin));
00531
00532 if (addr->ss.ss_family != AF_INET && option_debug >= 1) {
00533 ast_log(__LOG_DEBUG, file, line, func, "Address family is not AF_INET\n");
00534 }
00535
00536 addr->len = sizeof(*sin);
00537 }