aboutsummaryrefslogtreecommitdiff
path: root/src/nat/gnunet-service-nat_stun.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nat/gnunet-service-nat_stun.c')
-rw-r--r--src/nat/gnunet-service-nat_stun.c178
1 files changed, 90 insertions, 88 deletions
diff --git a/src/nat/gnunet-service-nat_stun.c b/src/nat/gnunet-service-nat_stun.c
index 639289207..d8b791d0a 100644
--- a/src/nat/gnunet-service-nat_stun.c
+++ b/src/nat/gnunet-service-nat_stun.c
@@ -11,12 +11,12 @@
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 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/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 17
18 SPDX-License-Identifier: AGPL3.0-or-later 18 SPDX-License-Identifier: AGPL3.0-or-later
19*/ 19 */
20/** 20/**
21 * This code provides some support for doing STUN transactions. We 21 * This code provides some support for doing STUN transactions. We
22 * receive the simplest possible packet as the STUN server and try 22 * receive the simplest possible packet as the STUN server and try
@@ -40,15 +40,14 @@
40#include "gnunet_util_lib.h" 40#include "gnunet_util_lib.h"
41#include "nat_stun.h" 41#include "nat_stun.h"
42 42
43#define LOG(kind,...) GNUNET_log_from (kind, "stun", __VA_ARGS__) 43#define LOG(kind, ...) GNUNET_log_from(kind, "stun", __VA_ARGS__)
44 44
45 45
46/** 46/**
47 * Context for #stun_get_mapped(). 47 * Context for #stun_get_mapped().
48 * Used to store state across processing attributes. 48 * Used to store state across processing attributes.
49 */ 49 */
50struct StunState 50struct StunState {
51{
52 uint16_t attr; 51 uint16_t attr;
53}; 52};
54 53
@@ -65,41 +64,44 @@ struct StunState
65 * @return #GNUNET_OK if @a arg was initialized 64 * @return #GNUNET_OK if @a arg was initialized
66 */ 65 */
67static int 66static int
68stun_get_mapped (struct StunState *st, 67stun_get_mapped(struct StunState *st,
69 const struct stun_attr *attr, 68 const struct stun_attr *attr,
70 uint32_t magic, 69 uint32_t magic,
71 struct sockaddr_in *arg) 70 struct sockaddr_in *arg)
72{ 71{
73 const struct stun_addr *returned_addr; 72 const struct stun_addr *returned_addr;
74 struct sockaddr_in *sa = (struct sockaddr_in *) arg; 73 struct sockaddr_in *sa = (struct sockaddr_in *)arg;
75 uint16_t type = ntohs (attr->attr); 74 uint16_t type = ntohs(attr->attr);
76 75
77 switch (type) 76 switch (type)
78 { 77 {
79 case STUN_MAPPED_ADDRESS: 78 case STUN_MAPPED_ADDRESS:
80 if ( (st->attr == STUN_XOR_MAPPED_ADDRESS) || 79 if ((st->attr == STUN_XOR_MAPPED_ADDRESS) ||
81 (st->attr == STUN_MS_XOR_MAPPED_ADDRESS) ) 80 (st->attr == STUN_MS_XOR_MAPPED_ADDRESS))
82 return GNUNET_NO; 81 return GNUNET_NO;
83 magic = 0; 82 magic = 0;
84 break; 83 break;
85 case STUN_MS_XOR_MAPPED_ADDRESS: 84
86 if (st->attr == STUN_XOR_MAPPED_ADDRESS) 85 case STUN_MS_XOR_MAPPED_ADDRESS:
86 if (st->attr == STUN_XOR_MAPPED_ADDRESS)
87 return GNUNET_NO;
88 break;
89
90 case STUN_XOR_MAPPED_ADDRESS:
91 break;
92
93 default:
87 return GNUNET_NO; 94 return GNUNET_NO;
88 break; 95 }
89 case STUN_XOR_MAPPED_ADDRESS: 96
90 break; 97 if (ntohs(attr->len) < sizeof(struct stun_addr))
91 default:
92 return GNUNET_NO;
93 }
94
95 if (ntohs (attr->len) < sizeof (struct stun_addr))
96 return GNUNET_NO; 98 return GNUNET_NO;
97 returned_addr = (const struct stun_addr *)(attr + 1); 99 returned_addr = (const struct stun_addr *)(attr + 1);
98 if (AF_INET != returned_addr->family) 100 if (AF_INET != returned_addr->family)
99 return GNUNET_NO; 101 return GNUNET_NO;
100 st->attr = type; 102 st->attr = type;
101 sa->sin_family = AF_INET; 103 sa->sin_family = AF_INET;
102 sa->sin_port = returned_addr->port ^ htons (ntohl(magic) >> 16); 104 sa->sin_port = returned_addr->port ^ htons(ntohl(magic) >> 16);
103 sa->sin_addr.s_addr = returned_addr->addr ^ magic; 105 sa->sin_addr.s_addr = returned_addr->addr ^ magic;
104 return GNUNET_OK; 106 return GNUNET_OK;
105} 107}
@@ -119,9 +121,9 @@ stun_get_mapped (struct StunState *st,
119 * #GNUNET_NO if the packet is invalid (not a stun packet) 121 * #GNUNET_NO if the packet is invalid (not a stun packet)
120 */ 122 */
121int 123int
122GNUNET_NAT_stun_handle_packet_ (const void *data, 124GNUNET_NAT_stun_handle_packet_(const void *data,
123 size_t len, 125 size_t len,
124 struct sockaddr_in *arg) 126 struct sockaddr_in *arg)
125{ 127{
126 const struct stun_header *hdr; 128 const struct stun_header *hdr;
127 const struct stun_attr *attr; 129 const struct stun_attr *attr;
@@ -135,76 +137,76 @@ GNUNET_NAT_stun_handle_packet_ (const void *data,
135 * while 'data' is advanced accordingly. 137 * while 'data' is advanced accordingly.
136 */ 138 */
137 if (len < sizeof(struct stun_header)) 139 if (len < sizeof(struct stun_header))
138 { 140 {
139 LOG (GNUNET_ERROR_TYPE_DEBUG, 141 LOG(GNUNET_ERROR_TYPE_DEBUG,
140 "Packet too short to be a STUN packet\n"); 142 "Packet too short to be a STUN packet\n");
141 return GNUNET_NO; 143 return GNUNET_NO;
142 } 144 }
143 hdr = data; 145 hdr = data;
144 /* Skip header as it is already in hdr */ 146 /* Skip header as it is already in hdr */
145 len -= sizeof(struct stun_header); 147 len -= sizeof(struct stun_header);
146 data += sizeof(struct stun_header); 148 data += sizeof(struct stun_header);
147 149
148 /* len as advertised in the message */ 150 /* len as advertised in the message */
149 advertised_message_size = ntohs (hdr->msglen); 151 advertised_message_size = ntohs(hdr->msglen);
150 message_magic_cookie = ntohl (hdr->magic); 152 message_magic_cookie = ntohl(hdr->magic);
151 /* Compare if the cookie match */ 153 /* Compare if the cookie match */
152 if (STUN_MAGIC_COOKIE != message_magic_cookie) 154 if (STUN_MAGIC_COOKIE != message_magic_cookie)
153 { 155 {
154 LOG (GNUNET_ERROR_TYPE_DEBUG, 156 LOG(GNUNET_ERROR_TYPE_DEBUG,
155 "Invalid magic cookie for STUN packet\n"); 157 "Invalid magic cookie for STUN packet\n");
156 return GNUNET_NO; 158 return GNUNET_NO;
157 } 159 }
158 160
159 LOG (GNUNET_ERROR_TYPE_INFO, 161 LOG(GNUNET_ERROR_TYPE_INFO,
160 "STUN Packet, msg %s (%04x), length: %d\n", 162 "STUN Packet, msg %s (%04x), length: %d\n",
161 stun_msg2str (ntohs (hdr->msgtype)), 163 stun_msg2str(ntohs(hdr->msgtype)),
162 ntohs (hdr->msgtype), 164 ntohs(hdr->msgtype),
163 advertised_message_size); 165 advertised_message_size);
164 if (advertised_message_size > len) 166 if (advertised_message_size > len)
165 {
166 LOG (GNUNET_ERROR_TYPE_INFO,
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));
174
175 while (len > 0)
176 {
177 if (len < sizeof (struct stun_attr))
178 { 167 {
179 LOG (GNUNET_ERROR_TYPE_INFO, 168 LOG(GNUNET_ERROR_TYPE_INFO,
180 "Attribute too short (got %d, expecting %d)\n", 169 "Scrambled STUN packet length (got %d, expecting %d)\n",
181 (int) len, 170 advertised_message_size,
182 (int) sizeof (struct stun_attr)); 171 (int)len);
183 break; 172 return GNUNET_NO;
184 } 173 }
185 attr = (const struct stun_attr *) data; 174 len = advertised_message_size;
186 175 memset(&st, 0, sizeof(st));
187 /* compute total attribute length */
188 advertised_message_size = ntohs (attr->len) + sizeof (struct stun_attr);
189 176
190 /* Check if we still have space in our buffer */ 177 while (len > 0)
191 if (advertised_message_size > len)
192 { 178 {
193 LOG (GNUNET_ERROR_TYPE_INFO, 179 if (len < sizeof(struct stun_attr))
194 "Inconsistent attribute (length %d exceeds remaining msg len %d)\n", 180 {
195 advertised_message_size, 181 LOG(GNUNET_ERROR_TYPE_INFO,
196 (int) len); 182 "Attribute too short (got %d, expecting %d)\n",
197 break; 183 (int)len,
184 (int)sizeof(struct stun_attr));
185 break;
186 }
187 attr = (const struct stun_attr *)data;
188
189 /* compute total attribute length */
190 advertised_message_size = ntohs(attr->len) + sizeof(struct stun_attr);
191
192 /* Check if we still have space in our buffer */
193 if (advertised_message_size > len)
194 {
195 LOG(GNUNET_ERROR_TYPE_INFO,
196 "Inconsistent attribute (length %d exceeds remaining msg len %d)\n",
197 advertised_message_size,
198 (int)len);
199 break;
200 }
201 if (GNUNET_OK ==
202 stun_get_mapped(&st,
203 attr,
204 hdr->magic,
205 arg))
206 ret = GNUNET_OK;
207 data += advertised_message_size;
208 len -= advertised_message_size;
198 } 209 }
199 if (GNUNET_OK ==
200 stun_get_mapped (&st,
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; 210 return ret;
209} 211}
210 212