2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2011 Daniel Borkmann.
5 * 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>
26 extern int print_stun_probe(char *server
, int sport
, int tport
);
28 #define BINDING_REQUEST 0x0001
29 #define BINDING_RESPONSE 0x0101
31 #define MAPPED_ADDRESS 0x0001
34 #define REQUEST_LEN 20
36 #define ID_COOKIE_FIELD htonl(((int) 'a' << 24) + \
44 uint32_t magic_cookie
;
54 struct stun_mapped_addr
{
61 static int stun_test(const char *server_ip
, int server_port
,
64 int ret
, sock
, set
= 1;
69 struct timeval timeout
;
70 struct stun_header
*hdr
, *rhdr
;
71 struct stun_attrib
*attr
;
72 struct stun_mapped_addr
*addr
;
73 struct sockaddr_in saddr
, daddr
;
79 sock
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
81 panic("Cannot obtain socket!\n");
83 ret
= setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
, &set
, sizeof(set
));
85 panic("Cannot set socket option!\n");
87 saddr
.sin_family
= PF_INET
;
88 saddr
.sin_port
= htons(tun_port
);
89 saddr
.sin_addr
.s_addr
= INADDR_ANY
;
91 ret
= bind(sock
, (struct sockaddr
*) &saddr
, sizeof(saddr
));
93 panic("Cannot bind udp socket!\n");
96 hdr
= (struct stun_header
*) pkt
;
97 hdr
->type
= htons(BINDING_REQUEST
);
99 hdr
->magic_cookie
= ID_COOKIE_FIELD
;
100 hdr
->transid
[0] = htonl(rand());
101 hdr
->transid
[1] = htonl(rand());
102 hdr
->transid
[2] = htonl(rand());
104 daddr
.sin_family
= PF_INET
;
105 daddr
.sin_port
= htons(server_port
);
106 daddr
.sin_addr
.s_addr
= inet_addr(server_ip
);
108 ret
= sendto(sock
, pkt
, len
, 0, (struct sockaddr
*) &daddr
,
111 whine("Error sending request (%s)!\n", strerror(errno
));
115 set_timeout(&timeout
, TIMEOUT
);
118 FD_SET(sock
, &fdset
);
120 ret
= select(sock
+ 1, &fdset
, NULL
, NULL
, &timeout
);
122 whine("STUN server timeout!\n");
126 memset(rpkt
, 0, sizeof(rpkt
));
127 len
= read(sock
, rpkt
, sizeof(rpkt
));
131 if (len
< REQUEST_LEN
) {
132 whine("Bad STUN response (%s)!\n", strerror(errno
));
136 rhdr
= (struct stun_header
*) rpkt
;
137 if (ntohs(rhdr
->type
) != BINDING_RESPONSE
) {
138 whine("Wrong STUN response type!\n");
142 if (rhdr
->len
== 0) {
143 whine("No attributes in STUN response!\n");
147 if (rhdr
->magic_cookie
!= hdr
->magic_cookie
||
148 rhdr
->transid
[0] != hdr
->transid
[0] ||
149 rhdr
->transid
[1] != hdr
->transid
[1] ||
150 rhdr
->transid
[2] != hdr
->transid
[2]) {
151 whine("Got wrong STUN transaction id!\n");
156 max
= ntohs(rhdr
->len
) + REQUEST_LEN
;
158 while (off
+ 8 < max
) {
159 attr
= (struct stun_attrib
*) (rpkt
+ off
);
160 if (ntohs(attr
->type
) != MAPPED_ADDRESS
)
163 addr
= (struct stun_mapped_addr
*) (rpkt
+ off
+ 4);
164 if (addr
->family
!= 0x1)
167 in
.s_addr
= addr
->ip
;
168 printf("Public mapping %s:%u!\n",
169 inet_ntoa(in
), ntohs(addr
->port
));
173 off
+= ntohs(attr
->len
);
179 int print_stun_probe(char *server
, int sport
, int tport
)
184 printf("STUN on %s:%u\n", server
, sport
);
187 hp
= gethostbyname(server
);
190 address
= inet_ntoa(*(struct in_addr
*) hp
->h_addr_list
[0]);
191 return stun_test(address
, sport
, tport
);