GNUnet 0.21.0
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
51{
52 uint16_t attr;
53};
54
55
67static 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
124int
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 ==
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 */
static int ret
Final status code.
Definition: gnunet-arm.c:94
static struct GNUNET_SCHEDULER_Task * st
The shutdown task.
static char * data
The data to insert into the dht.
static uint32_t type
Type string converted to DNS type value.
int GNUNET_NAT_stun_handle_packet_(const void *data, size_t len, struct sockaddr_in *arg)
Handle an incoming STUN response.
#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_OK
@ GNUNET_NO
@ GNUNET_SYSERR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
Message types for STUN server resolution.
#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
@ 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
Context for stun_get_mapped().
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
uint16_t msglen
Definition: nat_stun.h:45
uint16_t msgtype
Definition: nat_stun.h:44
uint32_t magic
Definition: nat_stun.h:46