|
|
|
|
|
Obtain the padded length of an attribute's value.
|
|
|
|
|
|
set a switch_stun_packet_attribute_t pointer to point at the first attribute in a packet
|
|
|
Obtain the correct length in bytes of a stun packet.
|
|
|
|
|
|
Increment an attribute pointer to the next attribute in it's packet.
|
|
|
00060 {
00061 SWITCH_STUN_ATTR_MAPPED_ADDRESS = 0x0001, /* Address */
00062 SWITCH_STUN_ATTR_RESPONSE_ADDRESS = 0x0002, /* Address */
00063 SWITCH_STUN_ATTR_CHANGE_REQUEST = 0x0003, /* UInt32 */
00064 SWITCH_STUN_ATTR_SOURCE_ADDRESS = 0x0004, /* Address */
00065 SWITCH_STUN_ATTR_CHANGED_ADDRESS = 0x0005, /* Address */
00066 SWITCH_STUN_ATTR_USERNAME = 0x0006, /* ByteString, multiple of 4 bytes */
00067 SWITCH_STUN_ATTR_PASSWORD = 0x0007, /* ByteString, multiple of 4 bytes */
00068 SWITCH_STUN_ATTR_MESSAGE_INTEGRITY = 0x0008, /* ByteString, 20 bytes */
00069 SWITCH_STUN_ATTR_ERROR_CODE = 0x0009, /* ErrorCode */
00070 SWITCH_STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000a, /* UInt16List */
00071 SWITCH_STUN_ATTR_REFLECTED_FROM = 0x000b, /* Address */
00072 SWITCH_STUN_ATTR_TRANSPORT_PREFERENCES = 0x000c, /* TransportPrefs */
00073 SWITCH_STUN_ATTR_LIFETIME = 0x000d, /* UInt32 */
00074 SWITCH_STUN_ATTR_ALTERNATE_SERVER = 0x000e, /* Address */
00075 SWITCH_STUN_ATTR_MAGIC_COOKIE = 0x000f, /* ByteString, 4 bytes */
00076 SWITCH_STUN_ATTR_BANDWIDTH = 0x0010, /* UInt32 */
00077 SWITCH_STUN_ATTR_DESTINATION_ADDRESS = 0x0011, /* Address */
00078 SWITCH_STUN_ATTR_SOURCE_ADDRESS2 = 0x0012, /* Address */
00079 SWITCH_STUN_ATTR_DATA = 0x0013, /* ByteString */
00080 SWITCH_STUN_ATTR_OPTIONS = 0x8001 /* UInt32 */
00081 } switch_stun_attribute_t;
|
|
|
00083 {
00084 SWITCH_STUN_ERROR_BAD_REQUEST = 400,
00085 SWITCH_STUN_ERROR_UNAUTHORIZED = 401,
00086 SWITCH_STUN_ERROR_UNKNOWN_ATTRIBUTE = 420,
00087 SWITCH_STUN_ERROR_STALE_CREDENTIALS = 430,
00088 SWITCH_STUN_ERROR_INTEGRITY_CHECK_FAILURE = 431,
00089 SWITCH_STUN_ERROR_MISSING_USERNAME = 432,
00090 SWITCH_STUN_ERROR_USE_TLS = 433,
00091 SWITCH_STUN_ERROR_SERVER_ERROR = 500,
00092 SWITCH_STUN_ERROR_GLOBAL_FAILURE = 600
00093 } switch_stun_error_t;
|
|
|
00044 {
00045 SWITCH_STUN_BINDING_REQUEST = 0x0001,
00046 SWITCH_STUN_BINDING_RESPONSE = 0x0101,
00047 SWITCH_STUN_BINDING_ERROR_RESPONSE = 0x0111,
00048 SWITCH_STUN_SHARED_SECRET_REQUEST = 0x0002,
00049 SWITCH_STUN_SHARED_SECRET_RESPONSE = 0x0102,
00050 SWITCH_STUN_SHARED_SECRET_ERROR_RESPONSE = 0x0112,
00051 SWITCH_STUN_ALLOCATE_REQUEST = 0x0003,
00052 SWITCH_STUN_ALLOCATE_RESPONSE = 0x0103,
00053 SWITCH_STUN_ALLOCATE_ERROR_RESPONSE = 0x0113,
00054 SWITCH_STUN_SEND_REQUEST = 0x0004,
00055 SWITCH_STUN_SEND_RESPONSE = 0x0104,
00056 SWITCH_STUN_SEND_ERROR_RESPONSE = 0x0114,
00057 SWITCH_STUN_DATA_INDICATION = 0x0115
00058 } switch_stun_message_t;
|
|
|
00095 {
00096 SWITCH_STUN_TYPE_PACKET_TYPE,
00097 SWITCH_STUN_TYPE_ATTRIBUTE,
00098 SWITCH_STUN_TYPE_ERROR
00099 } switch_stun_type_t;
|
|
||||||||||||||||||||||||||||
|
Perform a stun lookup.
00433 {
00434 switch_sockaddr_t *local_addr = NULL, *remote_addr = NULL, *from_addr = NULL;
00435 switch_socket_t *sock = NULL;
00436 uint8_t buf[260] = { 0 };
00437 uint8_t *start = buf;
00438 void *end_buf;
00439 switch_stun_packet_t *packet;
00440 switch_stun_packet_attribute_t *attr;
00441 switch_size_t bytes = 0;
00442 char username[33] = { 0 };
00443 char rip[16] = { 0 };
00444 uint16_t rport = 0;
00445 switch_time_t started = 0;
00446 unsigned int elapsed = 0;
00447 int funny = 0;
00448 int size = sizeof(buf);
00449
00450 switch_assert(err);
00451
00452 if (!strcmp(*err, "funny")) {
00453 funny = 1;
00454 }
00455
00456 *err = "Success";
00457
00458 switch_sockaddr_info_get(&from_addr, NULL, SWITCH_UNSPEC, 0, 0, pool);
00459
00460 if (switch_sockaddr_info_get(&local_addr, *ip, SWITCH_UNSPEC, *port, 0, pool) != SWITCH_STATUS_SUCCESS) {
00461 *err = "Local Address Error!";
00462 return SWITCH_STATUS_FALSE;
00463 }
00464
00465 if (switch_sockaddr_info_get(&remote_addr, stunip, SWITCH_UNSPEC, stunport, 0, pool) != SWITCH_STATUS_SUCCESS) {
00466 *err = "Remote Address Error!";
00467 return SWITCH_STATUS_FALSE;
00468 }
00469
00470 if (switch_socket_create(&sock, AF_INET, SOCK_DGRAM, 0, pool) != SWITCH_STATUS_SUCCESS) {
00471 *err = "Socket Error!";
00472 return SWITCH_STATUS_FALSE;
00473 }
00474
00475 if (switch_socket_bind(sock, local_addr) != SWITCH_STATUS_SUCCESS) {
00476 *err = "Bind Error!";
00477 return SWITCH_STATUS_FALSE;
00478 }
00479
00480 if (funny) {
00481 *start++ = 0;
00482 *start++ = 0;
00483 *start++ = 0x22;
00484 *start++ = 0x22;
00485 }
00486
00487 switch_socket_opt_set(sock, SWITCH_SO_NONBLOCK, TRUE);
00488 packet = switch_stun_packet_build_header(SWITCH_STUN_BINDING_REQUEST, NULL, start);
00489 switch_stun_random_string(username, 32, NULL);
00490 switch_stun_packet_attribute_add_username(packet, username, 32);
00491 bytes = switch_stun_packet_length(packet);
00492
00493 if (funny) {
00494 packet = (switch_stun_packet_t *) buf;
00495 bytes += 4;
00496 buf[bytes++] = 0;
00497 buf[bytes++] = 0;
00498 buf[bytes++] = 0;
00499 buf[bytes++] = 0;
00500 }
00501
00502 switch_socket_sendto(sock, remote_addr, 0, (void *) packet, &bytes);
00503 started = switch_timestamp_now();
00504
00505 *ip = NULL;
00506 *port = 0;
00507
00508
00509 for (;;) {
00510 bytes = sizeof(buf);
00511 if (switch_socket_recvfrom(from_addr, sock, 0, (char *) &buf, &bytes) == SWITCH_STATUS_SUCCESS && bytes > 0) {
00512 break;
00513 }
00514
00515 if ((elapsed = (unsigned int) ((switch_timestamp_now() - started) / 1000)) > 5000) {
00516 *err = "Timeout";
00517 switch_socket_shutdown(sock, SWITCH_SHUTDOWN_READWRITE);
00518 switch_socket_close(sock);
00519 return SWITCH_STATUS_TIMEOUT;
00520 }
00521 switch_yield(1000);
00522 }
00523 switch_socket_close(sock);
00524
00525 if (funny) {
00526 size -= 4;
00527 }
00528
00529 packet = switch_stun_packet_parse(start, size);
00530 if (!packet) {
00531 *err = "Invalid STUN/ICE packet";
00532 return SWITCH_STATUS_FALSE;
00533 }
00534 end_buf = buf + ((sizeof(buf) > packet->header.length) ? packet->header.length : sizeof(buf));
00535
00536 switch_stun_packet_first_attribute(packet, attr);
00537 do {
00538 switch (attr->type) {
00539 case SWITCH_STUN_ATTR_MAPPED_ADDRESS:
00540 if (attr->type) {
00541 if (funny) {
00542 ((switch_stun_ip_t *) attr->value)->address ^= ntohl(0xabcdabcd);
00543 }
00544 switch_stun_packet_attribute_get_mapped_address(attr, rip, &rport);
00545 }
00546 break;
00547 case SWITCH_STUN_ATTR_USERNAME:
00548 if (attr->type) {
00549 switch_stun_packet_attribute_get_username(attr, username, 32);
00550 }
00551 break;
00552 }
00553 } while (switch_stun_packet_next_attribute(attr, end_buf));
00554
00555 if (packet->header.type == SWITCH_STUN_BINDING_RESPONSE) {
00556 *ip = switch_core_strdup(pool, rip);
00557 *port = rport;
00558 return SWITCH_STATUS_SUCCESS;
00559 } else {
00560 *err = "Invalid Reply";
00561 }
00562
00563 return SWITCH_STATUS_FALSE;
00564 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Add a binded address packet attribute.
00383 {
00384 switch_stun_packet_attribute_t *attribute;
00385 switch_stun_ip_t *ip;
00386 uint8_t *i, x;
00387 char *p = ipstr;
00388
00389 attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) &packet->first_attribute + ntohs(packet->header.length));
00390 attribute->type = htons(SWITCH_STUN_ATTR_MAPPED_ADDRESS);
00391 attribute->length = htons(8);
00392 ip = (switch_stun_ip_t *) attribute->value;
00393
00394 ip->port = htons(port);
00395 ip->family = 1;
00396 i = (uint8_t *) &ip->address;
00397
00398 for (x = 0; x < 4; x++) {
00399 i[x] = (uint8_t) atoi(p);
00400 if ((p = strchr(p, '.'))) {
00401 p++;
00402 } else {
00403 break;
00404 }
00405 }
00406
00407 packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length;
00408 return 1;
00409 }
|
|
||||||||||||||||
|
Add a username packet attribute.
00412 {
00413 switch_stun_packet_attribute_t *attribute;
00414
00415 if (ulen % 4 != 0) {
00416 return 0;
00417 }
00418 attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) &packet->first_attribute + ntohs(packet->header.length));
00419 attribute->type = htons(SWITCH_STUN_ATTR_USERNAME);
00420 attribute->length = htons(ulen);
00421 if (username) {
00422 memcpy(attribute->value, username, ulen);
00423 } else {
00424 switch_stun_random_string(attribute->value, ulen, NULL);
00425 }
00426
00427 packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length;
00428 return 1;
00429 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Extract a mapped address (IP:PORT) from a packet attribute.
00340 {
00341 switch_stun_ip_t *ip;
00342 uint8_t x, *i;
00343 char *p = ipstr;
00344
00345 ip = (switch_stun_ip_t *) attribute->value;
00346 i = (uint8_t *) &ip->address;
00347 *ipstr = 0;
00348 for (x = 0; x < 4; x++) {
00349 sprintf(p, "%u%s", i[x], x == 3 ? "" : ".");
00350 p = ipstr + strlen(ipstr);
00351 }
00352 *port = ip->port;
00353 return 1;
00354 }
|
|
||||||||||||||||
|
Extract a username from a packet attribute.
00357 {
00358 uint16_t cpylen;
00359
00360 cpylen = attribute->length < len ? attribute->length : len;
00361 return memcpy(username, attribute->value, cpylen);
00362 }
|
|
||||||||||||||||
|
Prepare a new outbound packet of a certian type and id.
00365 {
00366 switch_stun_packet_header_t *header;
00367
00368
00369 header = (switch_stun_packet_header_t *) buf;
00370 header->type = htons(type);
00371 header->length = 0;
00372
00373 if (id) {
00374 memcpy(header->id, id, 16);
00375 } else {
00376 switch_stun_random_string(header->id, 16, NULL);
00377 }
00378
00379 return (switch_stun_packet_t *) buf;
00380 }
|
Here is the call graph for this function:

|
||||||||||||
|
Prepare a raw packet for parsing.
00118 {
00119 switch_stun_packet_t *packet;
00120 switch_stun_packet_attribute_t *attr;
00121 uint32_t bytes_left = len;
00122 void *end_buf = buf + len;
00123
00124 if (len < SWITCH_STUN_PACKET_MIN_LEN) {
00125 return NULL;
00126 }
00127
00128 packet = (switch_stun_packet_t *) buf;
00129 packet->header.type = ntohs(packet->header.type);
00130 packet->header.length = ntohs(packet->header.length);
00131 bytes_left -= packet->header.length + 20;
00132
00133 /*
00134 * Check packet type (RFC3489(bis?) values)
00135 */
00136 switch (packet->header.type) {
00137 case SWITCH_STUN_BINDING_REQUEST:
00138 case SWITCH_STUN_BINDING_RESPONSE:
00139 case SWITCH_STUN_BINDING_ERROR_RESPONSE:
00140 case SWITCH_STUN_SHARED_SECRET_REQUEST:
00141 case SWITCH_STUN_SHARED_SECRET_RESPONSE:
00142 case SWITCH_STUN_SHARED_SECRET_ERROR_RESPONSE:
00143 case SWITCH_STUN_ALLOCATE_REQUEST:
00144 case SWITCH_STUN_ALLOCATE_RESPONSE:
00145 case SWITCH_STUN_ALLOCATE_ERROR_RESPONSE:
00146 case SWITCH_STUN_SEND_REQUEST:
00147 case SWITCH_STUN_SEND_RESPONSE:
00148 case SWITCH_STUN_SEND_ERROR_RESPONSE:
00149 case SWITCH_STUN_DATA_INDICATION:
00150 /* Valid */
00151 break;
00152
00153 default:
00154 /* Invalid value */
00155 return NULL;
00156 }
00157
00158 /*
00159 * Check for length overflow
00160 */
00161 if (bytes_left <= 0) {
00162 /* Invalid */
00163 return NULL;
00164 }
00165
00166 /*
00167 * No payload?
00168 */
00169 if (packet->header.length == 0) {
00170 /* Invalid?! */
00171 return NULL;
00172 }
00173
00174 /* check if we have enough bytes left for an attribute */
00175 if (bytes_left < SWITCH_STUN_ATTRIBUTE_MIN_LEN) {
00176 return NULL;
00177 }
00178
00179 switch_stun_packet_first_attribute(packet, attr);
00180 do {
00181 attr->length = ntohs(attr->length);
00182 attr->type = ntohs(attr->type);
00183 bytes_left -= 4; /* attribute header consumed */
00184
00185 if (!attr->length || switch_stun_attribute_padded_length(attr) > bytes_left) {
00186 /*
00187 * Note we simply don't "break" here out of the loop anymore because
00188 * we don't want the upper layers to have to deal with attributes without a value
00189 * (or worse: invalid length)
00190 */
00191 return NULL;
00192 }
00193
00194 /*
00195 * Handle STUN attributes
00196 */
00197 switch (attr->type) {
00198 case SWITCH_STUN_ATTR_MAPPED_ADDRESS: /* Address, we only care about this one, but parse the others too */
00199 case SWITCH_STUN_ATTR_RESPONSE_ADDRESS:
00200 case SWITCH_STUN_ATTR_SOURCE_ADDRESS:
00201 case SWITCH_STUN_ATTR_CHANGED_ADDRESS:
00202 case SWITCH_STUN_ATTR_REFLECTED_FROM:
00203 case SWITCH_STUN_ATTR_ALTERNATE_SERVER:
00204 case SWITCH_STUN_ATTR_DESTINATION_ADDRESS:
00205 case SWITCH_STUN_ATTR_SOURCE_ADDRESS2:
00206 {
00207 switch_stun_ip_t *ip;
00208 uint32_t addr_length = 0;
00209 ip = (switch_stun_ip_t *) attr->value;
00210
00211 switch (ip->family) {
00212 case 0x01: /* IPv4 */
00213 addr_length = 4;
00214 break;
00215
00216 case 0x02: /* IPv6 */
00217 addr_length = 16;
00218 break;
00219
00220 default: /* Invalid */
00221 return NULL;
00222 }
00223
00224 /* attribute payload length must be == address length + size of other payload fields (family...) */
00225 if (attr->length != addr_length + 4) {
00226 /* Invalid */
00227 return NULL;
00228 }
00229
00230 ip->port = ntohs(ip->port);
00231 }
00232 break;
00233
00234 case SWITCH_STUN_ATTR_CHANGE_REQUEST: /* UInt32 */
00235 case SWITCH_STUN_ATTR_LIFETIME:
00236 case SWITCH_STUN_ATTR_BANDWIDTH:
00237 case SWITCH_STUN_ATTR_OPTIONS:
00238 {
00239 uint32_t *val = (uint32_t *) attr->value;
00240
00241 if (attr->length != sizeof(uint32_t)) {
00242 /* Invalid */
00243 return NULL;
00244 }
00245
00246 *val = ntohl(*val); /* should we do this here? */
00247 }
00248 break;
00249
00250 case SWITCH_STUN_ATTR_USERNAME: /* ByteString, multiple of 4 bytes */
00251 case SWITCH_STUN_ATTR_PASSWORD: /* ByteString, multiple of 4 bytes */
00252 if (attr->length % 4 != 0) {
00253 /* Invalid */
00254 return NULL;
00255 }
00256 break;
00257
00258 case SWITCH_STUN_ATTR_DATA: /* ByteString */
00259 case SWITCH_STUN_ATTR_ERROR_CODE: /* ErrorCode */
00260 case SWITCH_STUN_ATTR_TRANSPORT_PREFERENCES: /* TransportPrefs */
00261 /*
00262 * No length checking here, since we already checked against the padded length
00263 * before
00264 */
00265 break;
00266
00267 case SWITCH_STUN_ATTR_MESSAGE_INTEGRITY: /* ByteString, 20 bytes */
00268 if (attr->length != 20) {
00269 /* Invalid */
00270 return NULL;
00271 }
00272 break;
00273
00274 case SWITCH_STUN_ATTR_MAGIC_COOKIE: /* ByteString, 4 bytes */
00275 if (attr->length != 4) {
00276 /* Invalid */
00277 return NULL;
00278 }
00279 break;
00280
00281 case SWITCH_STUN_ATTR_UNKNOWN_ATTRIBUTES: /* UInt16List (= multiple of 2 bytes) */
00282 if (attr->length % 2 != 0) {
00283 return NULL;
00284 }
00285 break;
00286
00287 default:
00288 /* Mandatory attribute range? => invalid */
00289 if (attr->type <= 0x7FFF) {
00290 return NULL;
00291 }
00292 break;
00293 }
00294 bytes_left -= switch_stun_attribute_padded_length(attr); /* attribute value consumed, substract padded length */
00295
00296 } while (bytes_left >= SWITCH_STUN_ATTRIBUTE_MIN_LEN && switch_stun_packet_next_attribute(attr, end_buf));
00297
00298 if ((uint32_t) (packet->header.length + 20) > (uint32_t) (len - bytes_left)) {
00299 /*
00300 * the packet length is longer than the length of all attributes?
00301 * for now simply decrease the packet size
00302 */
00303 packet->header.length = (uint16_t) ((len - bytes_left) - 20);
00304 }
00305
00306 return packet;
00307 }
|
|
||||||||||||||||
|
Writes random characters into a buffer.
00097 {
00098 char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
00099 int max;
00100 uint16_t x;
00101
00102 if (!set) {
00103 set = chars;
00104 }
00105
00106 max = (int) strlen(set);
00107
00108 srand((unsigned int) switch_timestamp_now());
00109
00110 for (x = 0; x < len; x++) {
00111 int j = (int) (max * 1.0 * rand() / (RAND_MAX + 1.0));
00112 buf[x] = set[j];
00113 }
00114 }
|
Here is the call graph for this function:

|
||||||||||||
|
Obtain a printable string form of a given value.
00310 {
00311 uint32_t x = 0;
00312 const struct value_mapping *map = NULL;
00313 switch (type) {
00314 case SWITCH_STUN_TYPE_PACKET_TYPE:
00315 map = PACKET_TYPES;
00316 break;
00317 case SWITCH_STUN_TYPE_ATTRIBUTE:
00318 map = ATTR_TYPES;
00319 break;
00320 case SWITCH_STUN_TYPE_ERROR:
00321 map = ERROR_TYPES;
00322 break;
00323 default:
00324 map = NULL;
00325 break;
00326 }
00327
00328 if (map) {
00329 for (x = 0; map[x].value; x++) {
00330 if (map[x].value == value) {
00331 return map[x].name;
00332 }
00333 }
00334 }
00335
00336 return "INVALID";
00337 }
|
1.3.9.1