2 * transsip - the telephony network
3 * By Daniel Borkmann <daniel@transsip.org>
4 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
5 * Swiss federal institute of technology (ETH Zurich)
6 * Subject to the GPL, version 2.
16 #include <netinet/in.h>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
20 #include <sys/select.h>
27 /* Discovery type result */
29 #define RESULT_OPEN_INTERNET 1
30 #define RESULT_FIREWALL_BLOCKS_UDP 2
31 #define RESULT_SYMMETRIC_UDP_FIREWALL 3
32 #define RESULT_FULL_CONE_NAT 4
33 #define RESULT_SYMMETRIC_NAT 5
34 #define RESULT_RESTRICTED_CONE_NAT 6
35 #define RESULT_PORT_RESTR_CONE_NAT 7
38 #define BINDING_REQUEST 0x0001
39 #define BINDING_RESPONSE 0x0101
40 #define BINDING_ERROR_RESPONSE 0x0111
41 #define SHARED_SECRET_REQUEST 0x0002
42 #define SHARED_SECRET_RESPONSE 0x0102
43 #define SHARED_SECRET_ERROR_RESPONSE 0x0112
46 #define MAPPED_ADDRESS 0x0001
47 #define RESPONSE_ADDRESS 0x0002
48 #define CHANGE_REQUEST 0x0003
49 #define SOURCE_ADDRESS 0x0004
50 #define CHANGED_ADDRESS 0x0005
51 #define USERNAME 0x0006
52 #define PASSWORD 0x0007
53 #define MESSAGE_INTEGRITY 0x0008
54 #define ERROR_CODE 0x0009
55 #define UNKNOWN_ATTRIBUTES 0x000a
56 #define REFLECTED_FROM 0x000b
58 /* Error response codes */
59 #define ERROR_BAD_REQUEST 400
60 #define ERROR_UNAUTHORIZED 401
61 #define ERROR_UNKNOWN_ATTRIBUTE 420
62 #define ERROR_STALE_CREDENTIALS 430
63 #define ERROR_INTEGRITY_CHECK_FAIL 431
64 #define ERROR_MISSING_USERNAME 432
65 #define ERROR_USE_TLS 433
66 #define ERROR_SERVER_ERROR 500
67 #define ERROR_GLOBAL_FAILURE 600
70 #define REQUEST_LEN 20
72 #define ID_COOKIE_FIELD htonl(((int) 'a' << 24) + \
80 * Message length is the count, in bytes, of the size of the
81 * message, not including the 20 byte header. (RFC-3489)
85 * transid also serves as salt to randomize the request and the
86 * response. All responses carry the same identifier as
87 * the request they correspond to.
89 /* For the new RFC this would be 0x2112A442 in network Byte order. */
90 uint32_t magic_cookie
;
100 struct stun_mapped_addr
{
107 static int stun_test(const char *server_ip
, uint16_t server_port
,
110 int ret
, sock
, set
= 1;
113 size_t len
, off
, max
;
115 struct timeval timeout
;
116 struct stun_header
*hdr
, *rhdr
;
117 struct stun_attrib
*attr
;
118 struct stun_mapped_addr
*addr
;
119 struct sockaddr_in saddr
, daddr
;
125 sock
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
127 panic("Cannot obtain socket!\n");
129 ret
= setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
, &set
, sizeof(set
));
131 panic("Cannot set socket option!\n");
133 saddr
.sin_family
= PF_INET
;
134 saddr
.sin_port
= htons(tun_port
);
135 saddr
.sin_addr
.s_addr
= INADDR_ANY
;
137 ret
= bind(sock
, (struct sockaddr
*) &saddr
, sizeof(saddr
));
139 panic("Cannot bind udp socket!\n");
142 hdr
= (struct stun_header
*) pkt
;
143 hdr
->type
= htons(BINDING_REQUEST
);
145 hdr
->magic_cookie
= ID_COOKIE_FIELD
;
146 hdr
->transid
[0] = htonl(rand());
147 hdr
->transid
[1] = htonl(rand());
148 hdr
->transid
[2] = htonl(rand());
150 daddr
.sin_family
= PF_INET
;
151 daddr
.sin_port
= htons(server_port
);
152 daddr
.sin_addr
.s_addr
= inet_addr(server_ip
);
154 ret
= sendto(sock
, pkt
, len
, 0, (struct sockaddr
*) &daddr
,
157 whine("Error sending request (%s)!\n", strerror(errno
));
161 set_timeout(&timeout
, TIMEOUT
);
164 FD_SET(sock
, &fdset
);
166 ret
= select(sock
+ 1, &fdset
, NULL
, NULL
, &timeout
);
168 whine("STUN server timeout!\n");
172 memset(rpkt
, 0, sizeof(rpkt
));
173 len
= read(sock
, rpkt
, sizeof(rpkt
));
177 if (len
< REQUEST_LEN
) {
178 whine("Bad STUN response (%s)!\n", strerror(errno
));
182 rhdr
= (struct stun_header
*) rpkt
;
183 if (ntohs(rhdr
->type
) != BINDING_RESPONSE
) {
184 whine("Wrong STUN response type!\n");
188 if (rhdr
->len
== 0) {
189 whine("No attributes in STUN response!\n");
193 if (rhdr
->magic_cookie
!= hdr
->magic_cookie
||
194 rhdr
->transid
[0] != hdr
->transid
[0] ||
195 rhdr
->transid
[1] != hdr
->transid
[1] ||
196 rhdr
->transid
[2] != hdr
->transid
[2]) {
197 whine("Got wrong STUN transaction id!\n");
202 max
= ntohs(rhdr
->len
) + REQUEST_LEN
;
204 while (off
+ 8 < max
) {
205 attr
= (struct stun_attrib
*) (rpkt
+ off
);
206 if (ntohs(attr
->type
) != MAPPED_ADDRESS
)
209 addr
= (struct stun_mapped_addr
*) (rpkt
+ off
+ 4);
210 if (addr
->family
!= 0x1)
213 in
.s_addr
= addr
->ip
;
214 info("Public mapping %s:%u!\n", inet_ntoa(in
), ntohs(addr
->port
));
218 off
+= ntohs(attr
->len
);
224 void print_stun_probe(char *server
, uint16_t sport
, uint16_t tunport
)
229 printf("STUN on %s:%u\n", server
, sport
);
231 hp
= gethostbyname(server
);
234 address
= inet_ntoa(*(struct in_addr
*) hp
->h_addr_list
[0]);
235 stun_test(address
, sport
, tunport
);