GNUnet 0.22.2
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"
43
44#define LOG(kind, ...) GNUNET_log_from (kind, "stun", __VA_ARGS__)
45
46
52{
53 uint16_t attr;
54};
55
56
68static int
70 const struct stun_attr *attr,
71 uint32_t magic,
72 struct sockaddr_in *arg)
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}
110
111
125int
127 size_t len,
128 struct sockaddr_in *arg)
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}
214
215
216/* end of gnunet-service-nat_stun.c */
static int ret
Final status code.
Definition: gnunet-arm.c:93
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.
This code provides some support for doing STUN transactions.
@ 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