GNUnet  0.10.x
Data Structures | Macros | Functions
gnunet-service-nat_stun.c File Reference

This code provides some support for doing STUN transactions. More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "nat_stun.h"
Include dependency graph for gnunet-service-nat_stun.c:

Go to the source code of this file.

Data Structures

struct  StunState
 Context for stun_get_mapped(). More...


#define LOG(kind, ...)   GNUNET_log_from (kind, "stun", __VA_ARGS__)


static int stun_get_mapped (struct StunState *st, const struct stun_attr *attr, uint32_t magic, struct sockaddr_in *arg)
 Extract the STUN_MAPPED_ADDRESS from the stun response. More...
int GNUNET_NAT_stun_handle_packet_ (const void *data, size_t len, struct sockaddr_in *arg)
 Handle an incoming STUN response. More...

Detailed Description

This code provides some support for doing STUN transactions.

We receive the simplest possible packet as the STUN server and try to respond properly.

All STUN packets start with a simple header made of a type, length (excluding the header) and a 16-byte random transaction id. Following the header we may have zero or more attributes, each structured as a type, length and a value (whose format depends on the type, but often contains addresses). Of course all fields are in network format.

This code was based on ministun.c.

Functions for STUN functionality

Bruno Souza Cabral

Definition in file gnunet-service-nat_stun.c.

Macro Definition Documentation


#define LOG (   kind,
)    GNUNET_log_from (kind, "stun", __VA_ARGS__)

Definition at line 43 of file gnunet-service-nat_stun.c.

Referenced by GNUNET_NAT_stun_handle_packet_().

Function Documentation

◆ stun_get_mapped()

static int stun_get_mapped ( struct StunState st,
const struct stun_attr attr,
uint32_t  magic,
struct sockaddr_in *  arg 

Extract the STUN_MAPPED_ADDRESS from the stun response.

This is used as a callback for stun_handle_response when called from stun_request.

[out]stpointer where we will set the type
attrreceived stun attribute
magicMagic cookie
[out]argpointer to a sockaddr_in where we will set the reported IP and port
GNUNET_OK if arg was initialized

Definition at line 68 of file gnunet-service-nat_stun.c.

References stun_addr::addr, stun_attr::attr, StunState::attr, stun_addr::family, GNUNET_NO, GNUNET_OK, stun_attr::len, stun_addr::port, STUN_MAPPED_ADDRESS, STUN_MS_XOR_MAPPED_ADDRESS, STUN_XOR_MAPPED_ADDRESS, and type.

Referenced by GNUNET_NAT_stun_handle_packet_().

72 {
73  const struct stun_addr *returned_addr;
74  struct sockaddr_in *sa = (struct sockaddr_in *) arg;
75  uint16_t type = ntohs (attr->attr);
77  switch (type)
78  {
80  if ( (st->attr == STUN_XOR_MAPPED_ADDRESS) ||
82  return GNUNET_NO;
83  magic = 0;
84  break;
86  if (st->attr == STUN_XOR_MAPPED_ADDRESS)
87  return GNUNET_NO;
88  break;
90  break;
91  default:
92  return GNUNET_NO;
93  }
95  if (ntohs (attr->len) < sizeof (struct stun_addr))
96  return GNUNET_NO;
97  returned_addr = (const struct stun_addr *)(attr + 1);
98  if (AF_INET != returned_addr->family)
99  return GNUNET_NO;
100  st->attr = type;
101  sa->sin_family = AF_INET;
102  sa->sin_port = returned_addr->port ^ htons (ntohl(magic) >> 16);
103  sa->sin_addr.s_addr = returned_addr->addr ^ magic;
104  return GNUNET_OK;
105 }
uint16_t attr
Definition: nat_stun.h:52
uint16_t port
Port number.
Definition: nat_stun.h:72
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
uint32_t addr
IPv4 address.
Definition: nat_stun.h:77
The format normally used for addresses carried by STUN messages.
Definition: nat_stun.h:60
uint8_t family
Address family, we expect AF_INET.
Definition: nat_stun.h:67
uint16_t len
Definition: nat_stun.h:53
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
Here is the caller graph for this function:

◆ GNUNET_NAT_stun_handle_packet_()

int GNUNET_NAT_stun_handle_packet_ ( const void *  data,
size_t  len,
struct sockaddr_in *  arg 

Handle an incoming STUN response.

Do some basic sanity checks on packet size and content, try to extract information. At the moment this only processes BIND requests, and returns the externally visible address of the original request.

datathe packet
lenthe length of the packet in data
[out]argsockaddr_in where we will set our discovered address
GNUNET_OK on success, GNUNET_NO if the packet is invalid (not a stun packet)

Definition at line 122 of file gnunet-service-nat_stun.c.

References StunState::attr, data, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, stun_attr::len, LOG, stun_header::magic, stun_header::msglen, stun_header::msgtype, ret, stun_get_mapped(), STUN_MAGIC_COOKIE, and stun_msg2str().

Referenced by handle_stun().

125 {
126  const struct stun_header *hdr;
127  const struct stun_attr *attr;
128  struct StunState st;
129  uint32_t advertised_message_size;
130  uint32_t message_magic_cookie;
131  int ret = GNUNET_SYSERR;
133  /* On entry, 'len' is the length of the UDP payload. After the
134  * initial checks it becomes the size of unprocessed options,
135  * while 'data' is advanced accordingly.
136  */
137  if (len < sizeof(struct stun_header))
138  {
140  "Packet too short to be a STUN packet\n");
141  return GNUNET_NO;
142  }
143  hdr = data;
144  /* Skip header as it is already in hdr */
145  len -= sizeof(struct stun_header);
146  data += sizeof(struct stun_header);
148  /* len as advertised in the message */
149  advertised_message_size = ntohs (hdr->msglen);
150  message_magic_cookie = ntohl (hdr->magic);
151  /* Compare if the cookie match */
152  if (STUN_MAGIC_COOKIE != message_magic_cookie)
153  {
155  "Invalid magic cookie for STUN packet\n");
156  return GNUNET_NO;
157  }
160  "STUN Packet, msg %s (%04x), length: %d\n",
161  stun_msg2str (ntohs (hdr->msgtype)),
162  ntohs (hdr->msgtype),
163  advertised_message_size);
164  if (advertised_message_size > len)
165  {
167  "Scrambled STUN packet length (got %d, expecting %d)\n",
168  advertised_message_size,
169  (int) len);
170  return GNUNET_NO;
171  }
172  len = advertised_message_size;
173  memset (&st, 0, sizeof(st));
175  while (len > 0)
176  {
177  if (len < sizeof (struct stun_attr))
178  {
180  "Attribute too short (got %d, expecting %d)\n",
181  (int) len,
182  (int) sizeof (struct stun_attr));
183  break;
184  }
185  attr = (const struct stun_attr *) data;
187  /* compute total attribute length */
188  advertised_message_size = ntohs (attr->len) + sizeof (struct stun_attr);
190  /* Check if we still have space in our buffer */
191  if (advertised_message_size > len)
192  {
194  "Inconsistent attribute (length %d exceeds remaining msg len %d)\n",
195  advertised_message_size,
196  (int) len);
197  break;
198  }
199  if (GNUNET_OK ==
201  attr,
202  hdr->magic,
203  arg))
204  ret = GNUNET_OK;
205  data += advertised_message_size;
206  len -= advertised_message_size;
207  }
208  return ret;
209 }
Context for stun_get_mapped().
uint16_t attr
Definition: nat_stun.h:52
static int stun_get_mapped(struct StunState *st, const struct stun_attr *attr, uint32_t magic, struct sockaddr_in *arg)
Extract the STUN_MAPPED_ADDRESS from the stun response.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
uint16_t msglen
Definition: nat_stun.h:44
static int ret
Final status code.
Definition: gnunet-arm.c:89
uint16_t msgtype
Definition: nat_stun.h:43
Definition: gnunet_common.h:79
uint16_t len
Definition: nat_stun.h:53
#define LOG(kind,...)
Definition: nat_stun.h:34
static const char * stun_msg2str(int msg)
Print a class and method from a STUN message.
Definition: nat_stun.h:167
uint32_t magic
Definition: nat_stun.h:45
static struct GNUNET_SCHEDULER_Task * st
The shutdown task.
uint32_t data
The data value.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
Here is the call graph for this function:
Here is the caller graph for this function: