GNUnet 0.22.2
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 "gnunet-service-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...
 

Macros

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

Functions

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

Author
Bruno Souza Cabral

Definition in file gnunet-service-nat_stun.c.

Macro Definition Documentation

◆ LOG

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

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

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 
)
static

Extract the STUN_MAPPED_ADDRESS from the stun response.

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

Parameters
[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
Returns
GNUNET_OK if arg was initialized

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

73{
74 const struct stun_addr *returned_addr;
75 struct sockaddr_in *sa = (struct sockaddr_in *) arg;
76 uint16_t type = ntohs (attr->attr);
77
78 switch (type)
79 {
81 if ((st->attr == STUN_XOR_MAPPED_ADDRESS) ||
83 return GNUNET_NO;
84 magic = 0;
85 break;
86
88 if (st->attr == STUN_XOR_MAPPED_ADDRESS)
89 return GNUNET_NO;
90 break;
91
93 break;
94
95 default:
96 return GNUNET_NO;
97 }
98
99 if (ntohs (attr->len) < sizeof(struct stun_addr))
100 return GNUNET_NO;
101 returned_addr = (const struct stun_addr *) (attr + 1);
102 if (AF_INET != returned_addr->family)
103 return GNUNET_NO;
104 st->attr = type;
105 sa->sin_family = AF_INET;
106 sa->sin_port = returned_addr->port ^ htons (ntohl (magic) >> 16);
107 sa->sin_addr.s_addr = returned_addr->addr ^ magic;
108 return GNUNET_OK;
109}
static struct GNUNET_SCHEDULER_Task * st
The shutdown task.
static uint32_t type
Type string converted to DNS type value.
@ GNUNET_OK
@ GNUNET_NO
@ STUN_MS_XOR_MAPPED_ADDRESS
Definition: nat_stun.h:129
@ STUN_MAPPED_ADDRESS
Definition: nat_stun.h:114
@ STUN_XOR_MAPPED_ADDRESS
Definition: nat_stun.h:127
The format normally used for addresses carried by STUN messages.
Definition: nat_stun.h:62
uint8_t family
Address family, we expect AF_INET.
Definition: nat_stun.h:68
uint32_t addr
IPv4 address.
Definition: nat_stun.h:78
uint16_t port
Port number.
Definition: nat_stun.h:73
uint16_t len
Definition: nat_stun.h:54
uint16_t attr
Definition: nat_stun.h:53

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

Referenced by GNUNET_NAT_stun_handle_packet_().

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.

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

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

129{
130 const struct stun_header *hdr;
131 const struct stun_attr *attr;
132 struct StunState st;
133 uint32_t advertised_message_size;
134 uint32_t message_magic_cookie;
135 int ret = GNUNET_SYSERR;
136
137 /* On entry, 'len' is the length of the UDP payload. After the
138 * initial checks it becomes the size of unprocessed options,
139 * while 'data' is advanced accordingly.
140 */
141 if (len < sizeof(struct stun_header))
142 {
144 "Packet too short to be a STUN packet\n");
145 return GNUNET_NO;
146 }
147 hdr = data;
148 /* Skip header as it is already in hdr */
149 len -= sizeof(struct stun_header);
150 data += sizeof(struct stun_header);
151
152 /* len as advertised in the message */
153 advertised_message_size = ntohs (hdr->msglen);
154 message_magic_cookie = ntohl (hdr->magic);
155 /* Compare if the cookie match */
156 if (STUN_MAGIC_COOKIE != message_magic_cookie)
157 {
159 "Invalid magic cookie for STUN packet\n");
160 return GNUNET_NO;
161 }
162
164 "STUN Packet, msg %s (%04x), length: %d\n",
165 stun_msg2str (ntohs (hdr->msgtype)),
166 ntohs (hdr->msgtype),
167 advertised_message_size);
168 if (advertised_message_size > len)
169 {
171 "Scrambled STUN packet length (got %d, expecting %d)\n",
172 advertised_message_size,
173 (int) len);
174 return GNUNET_NO;
175 }
176 len = advertised_message_size;
177 memset (&st, 0, sizeof(st));
178
179 while (len > 0)
180 {
181 if (len < sizeof(struct stun_attr))
182 {
184 "Attribute too short (got %d, expecting %d)\n",
185 (int) len,
186 (int) sizeof(struct stun_attr));
187 break;
188 }
189 attr = (const struct stun_attr *) data;
190
191 /* compute total attribute length */
192 advertised_message_size = ntohs (attr->len) + sizeof(struct stun_attr);
193
194 /* Check if we still have space in our buffer */
195 if (advertised_message_size > len)
196 {
198 "Inconsistent attribute (length %d exceeds remaining msg len %d)\n",
199 advertised_message_size,
200 (int) len);
201 break;
202 }
203 if (GNUNET_OK ==
205 attr,
206 hdr->magic,
207 arg))
208 ret = GNUNET_OK;
209 data += advertised_message_size;
210 len -= advertised_message_size;
211 }
212 return ret;
213}
static int ret
Final status code.
Definition: gnunet-arm.c:93
static char * data
The data to insert into the dht.
#define LOG(kind,...)
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.
@ GNUNET_SYSERR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define STUN_MAGIC_COOKIE
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:173
Context for stun_get_mapped().
uint16_t msglen
Definition: nat_stun.h:45
uint16_t msgtype
Definition: nat_stun.h:44
uint32_t magic
Definition: nat_stun.h:46

References find_typedefs::arg, stun_attr::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, st, stun_get_mapped(), STUN_MAGIC_COOKIE, and stun_msg2str().

Referenced by handle_stun().

Here is the call graph for this function:
Here is the caller graph for this function: