GNUnet  0.11.x
gnunet-service-nat_stun.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009, 2015, 2016 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
39 #include "platform.h"
40 #include "gnunet_util_lib.h"
41 #include "nat_stun.h"
42 
43 #define LOG(kind, ...) GNUNET_log_from (kind, "stun", __VA_ARGS__)
44 
45 
50 struct StunState
51 {
52  uint16_t attr;
53 };
54 
55 
67 static int
69  const struct stun_attr *attr,
70  uint32_t magic,
71  struct sockaddr_in *arg)
72 {
73  const struct stun_addr *returned_addr;
74  struct sockaddr_in *sa = (struct sockaddr_in *) arg;
75  uint16_t type = ntohs (attr->attr);
76 
77  switch (type)
78  {
80  if ((st->attr == STUN_XOR_MAPPED_ADDRESS) ||
82  return GNUNET_NO;
83  magic = 0;
84  break;
85 
87  if (st->attr == STUN_XOR_MAPPED_ADDRESS)
88  return GNUNET_NO;
89  break;
90 
92  break;
93 
94  default:
95  return GNUNET_NO;
96  }
97 
98  if (ntohs (attr->len) < sizeof(struct stun_addr))
99  return GNUNET_NO;
100  returned_addr = (const struct stun_addr *) (attr + 1);
101  if (AF_INET != returned_addr->family)
102  return GNUNET_NO;
103  st->attr = type;
104  sa->sin_family = AF_INET;
105  sa->sin_port = returned_addr->port ^ htons (ntohl (magic) >> 16);
106  sa->sin_addr.s_addr = returned_addr->addr ^ magic;
107  return GNUNET_OK;
108 }
109 
110 
124 int
126  size_t len,
127  struct sockaddr_in *arg)
128 {
129  const struct stun_header *hdr;
130  const struct stun_attr *attr;
131  struct StunState st;
132  uint32_t advertised_message_size;
133  uint32_t message_magic_cookie;
134  int ret = GNUNET_SYSERR;
135 
136  /* On entry, 'len' is the length of the UDP payload. After the
137  * initial checks it becomes the size of unprocessed options,
138  * while 'data' is advanced accordingly.
139  */
140  if (len < sizeof(struct stun_header))
141  {
143  "Packet too short to be a STUN packet\n");
144  return GNUNET_NO;
145  }
146  hdr = data;
147  /* Skip header as it is already in hdr */
148  len -= sizeof(struct stun_header);
149  data += sizeof(struct stun_header);
150 
151  /* len as advertised in the message */
152  advertised_message_size = ntohs (hdr->msglen);
153  message_magic_cookie = ntohl (hdr->magic);
154  /* Compare if the cookie match */
155  if (STUN_MAGIC_COOKIE != message_magic_cookie)
156  {
158  "Invalid magic cookie for STUN packet\n");
159  return GNUNET_NO;
160  }
161 
163  "STUN Packet, msg %s (%04x), length: %d\n",
164  stun_msg2str (ntohs (hdr->msgtype)),
165  ntohs (hdr->msgtype),
166  advertised_message_size);
167  if (advertised_message_size > len)
168  {
170  "Scrambled STUN packet length (got %d, expecting %d)\n",
171  advertised_message_size,
172  (int) len);
173  return GNUNET_NO;
174  }
175  len = advertised_message_size;
176  memset (&st, 0, sizeof(st));
177 
178  while (len > 0)
179  {
180  if (len < sizeof(struct stun_attr))
181  {
183  "Attribute too short (got %d, expecting %d)\n",
184  (int) len,
185  (int) sizeof(struct stun_attr));
186  break;
187  }
188  attr = (const struct stun_attr *) data;
189 
190  /* compute total attribute length */
191  advertised_message_size = ntohs (attr->len) + sizeof(struct stun_attr);
192 
193  /* Check if we still have space in our buffer */
194  if (advertised_message_size > len)
195  {
197  "Inconsistent attribute (length %d exceeds remaining msg len %d)\n",
198  advertised_message_size,
199  (int) len);
200  break;
201  }
202  if (GNUNET_OK ==
203  stun_get_mapped (&st,
204  attr,
205  hdr->magic,
206  arg))
207  ret = GNUNET_OK;
208  data += advertised_message_size;
209  len -= advertised_message_size;
210  }
211  return ret;
212 }
213 
214 
215 /* end of gnunet-service-nat_stun.c */
Context for stun_get_mapped().
uint16_t attr
Definition: nat_stun.h:53
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.
Message types for STUN server resolution.
uint16_t port
Port number.
Definition: nat_stun.h:73
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t msglen
Definition: nat_stun.h:45
uint32_t addr
IPv4 address.
Definition: nat_stun.h:78
int GNUNET_NAT_stun_handle_packet_(const void *data, size_t len, struct sockaddr_in *arg)
Handle an incoming STUN response.
The format normally used for addresses carried by STUN messages.
Definition: nat_stun.h:61
uint16_t msgtype
Definition: nat_stun.h:44
uint8_t family
Address family, we expect AF_INET.
Definition: nat_stun.h:68
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
uint16_t len
Definition: nat_stun.h:54
#define LOG(kind,...)
#define STUN_MAGIC_COOKIE
Definition: nat_stun.h:34
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
static const char * stun_msg2str(int msg)
Print a class and method from a STUN message.
Definition: nat_stun.h:173
uint32_t magic
Definition: nat_stun.h:46
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...