/* This file is part of GNUnet. Copyright (C) 2009, 2015, 2016 GNUnet e.V. GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . SPDX-License-Identifier: AGPL3.0-or-later */ /** * Message types for STUN server resolution * * @file nat/nat_stun.h * @brief Testcase for STUN library * @author Bruno Souza Cabral * @autor Mark Spencer (Original code borrowed from Asterisk) * @author Christian Grothoff */ #define STUN_IGNORE (0) #define STUN_ACCEPT (1) #define STUN_MAGIC_COOKIE 0x2112A442 typedef struct { uint32_t id[3]; } GNUNET_PACKED stun_trans_id; struct stun_header { uint16_t msgtype; uint16_t msglen; uint32_t magic; stun_trans_id id; } GNUNET_PACKED; struct stun_attr { uint16_t attr; uint16_t len; } GNUNET_PACKED; /** * The format normally used for addresses carried by STUN messages. */ struct stun_addr { uint8_t unused; /** * Address family, we expect AF_INET. */ uint8_t family; /** * Port number. */ uint16_t port; /** * IPv4 address. Should this be "struct in_addr"? */ uint32_t addr; } GNUNET_PACKED; /** * STUN message classes */ enum StunClasses { INVALID_CLASS = 0, STUN_REQUEST = 0x0000, STUN_INDICATION = 0x0001, STUN_RESPONSE = 0x0002, STUN_ERROR_RESPONSE = 0x0003 }; enum StunMethods { INVALID_METHOD = 0, STUN_BINDING = 0x0001, STUN_SHARED_SECRET = 0x0002, STUN_ALLOCATE = 0x0003, STUN_REFRESH = 0x0004, STUN_SEND = 0x0006, STUN_DATA = 0x0007, STUN_CREATE_PERMISSION = 0x0008, STUN_CHANNEL_BIND = 0x0009 }; /** * Basic attribute types in stun messages. * Messages can also contain custom attributes (codes above 0x7fff) */ enum StunAttributes { STUN_MAPPED_ADDRESS = 0x0001, STUN_RESPONSE_ADDRESS = 0x0002, STUN_CHANGE_ADDRESS = 0x0003, STUN_SOURCE_ADDRESS = 0x0004, STUN_CHANGED_ADDRESS = 0x0005, STUN_USERNAME = 0x0006, STUN_PASSWORD = 0x0007, STUN_MESSAGE_INTEGRITY = 0x0008, STUN_ERROR_CODE = 0x0009, STUN_UNKNOWN_ATTRIBUTES = 0x000a, STUN_REFLECTED_FROM = 0x000b, STUN_REALM = 0x0014, STUN_NONCE = 0x0015, STUN_XOR_MAPPED_ADDRESS = 0x0020, STUN_MS_VERSION = 0x8008, STUN_MS_XOR_MAPPED_ADDRESS = 0x8020, STUN_SOFTWARE = 0x8022, STUN_ALTERNATE_SERVER = 0x8023, STUN_FINGERPRINT = 0x8028 }; /** * Convert a message to a StunClass * * @param msg the received message * @return the converted StunClass */ static enum StunClasses decode_class (int msg) { /* Sorry for the magic, but this maps the class according to rfc5245 */ return (enum StunClasses) ((msg & 0x0010) >> 4) | ((msg & 0x0100) >> 7); } /** * Convert a message to a StunMethod * * @param msg the received message * @return the converted StunMethod */ static enum StunMethods decode_method (int msg) { return (enum StunMethods) (msg & 0x000f) | ((msg & 0x00e0) >> 1) | ((msg & 0x3e00) >> 2); } /** * Print a class and method from a STUN message * * @param msg * @return string with the message class and method */ GNUNET_UNUSED static const char * stun_msg2str (int msg) { static const struct { enum StunClasses value; const char *name; } classes[] = { { STUN_REQUEST, "Request" }, { STUN_INDICATION, "Indication" }, { STUN_RESPONSE, "Response" }, { STUN_ERROR_RESPONSE, "Error Response" }, { INVALID_CLASS, NULL } }; static const struct { enum StunMethods value; const char *name; } methods[] = { { STUN_BINDING, "Binding" }, { INVALID_METHOD, NULL } }; static char result[64]; const char *msg_class = NULL; const char *method = NULL; enum StunClasses cvalue; enum StunMethods mvalue; cvalue = decode_class (msg); for (unsigned int i = 0; classes[i].name; i++) if (classes[i].value == cvalue) { msg_class = classes[i].name; break; } mvalue = decode_method (msg); for (unsigned int i = 0; methods[i].name; i++) if (methods[i].value == mvalue) { method = methods[i].name; break; } GNUNET_snprintf (result, sizeof(result), "%s %s", method ? : "Unknown Method", msg_class ? : "Unknown Class Message"); return result; } /** * Print attribute name * * @param msg with a attribute type * @return string with the attribute name */ GNUNET_UNUSED static const char * stun_attr2str (enum StunAttributes msg) { static const struct { enum StunAttributes value; const char *name; } attrs[] = { { STUN_MAPPED_ADDRESS, "Mapped Address" }, { STUN_RESPONSE_ADDRESS, "Response Address" }, { STUN_CHANGE_ADDRESS, "Change Address" }, { STUN_SOURCE_ADDRESS, "Source Address" }, { STUN_CHANGED_ADDRESS, "Changed Address" }, { STUN_USERNAME, "Username" }, { STUN_PASSWORD, "Password" }, { STUN_MESSAGE_INTEGRITY, "Message Integrity" }, { STUN_ERROR_CODE, "Error Code" }, { STUN_UNKNOWN_ATTRIBUTES, "Unknown Attributes" }, { STUN_REFLECTED_FROM, "Reflected From" }, { STUN_REALM, "Realm" }, { STUN_NONCE, "Nonce" }, { STUN_XOR_MAPPED_ADDRESS, "XOR Mapped Address" }, { STUN_MS_VERSION, "MS Version" }, { STUN_MS_XOR_MAPPED_ADDRESS, "MS XOR Mapped Address" }, { STUN_SOFTWARE, "Software" }, { STUN_ALTERNATE_SERVER, "Alternate Server" }, { STUN_FINGERPRINT, "Fingerprint" }, { 0, NULL } }; for (unsigned int i = 0; attrs[i].name; i++) if (attrs[i].value == msg) return attrs[i].name; return "Unknown Attribute"; } /* end of nat_stun.h */