1 //
2 //  SuperTuxKart - a fun racing game with go-kart
3 //  Copyright (C) 2015 Joerg Henrichs
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 3
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 #include "network/network_config.hpp"
20 #include "config/stk_config.hpp"
21 #include "config/user_config.hpp"
22 #include "input/device_manager.hpp"
23 #include "modes/world.hpp"
24 #include "network/network.hpp"
25 #include "network/network_string.hpp"
26 #include "network/rewind_manager.hpp"
27 #include "network/server_config.hpp"
28 #include "network/socket_address.hpp"
29 #include "network/stk_host.hpp"
30 #include "network/stk_ipv6.hpp"
31 #include "online/xml_request.hpp"
32 #include "states_screens/main_menu_screen.hpp"
33 #include "states_screens/online/networking_lobby.hpp"
34 #include "states_screens/online/online_lan.hpp"
35 #include "states_screens/online/online_profile_servers.hpp"
36 #include "states_screens/online/online_screen.hpp"
37 #include "states_screens/state_manager.hpp"
38 #include "utils/string_utils.hpp"
39 #include "utils/time.hpp"
40 #include "utils/utf8/unchecked.h"
41 
42 #ifdef WIN32
43 #  include <windns.h>
44 #  include <ws2tcpip.h>
45 #ifndef __MINGW32__
46 #  pragma comment(lib, "dnsapi.lib")
47 #endif
48 #else
49 #  include <arpa/nameser.h>
50 #  include <arpa/nameser_compat.h>
51 #  include <netdb.h>
52 #  include <netinet/in.h>
53 #  include <resolv.h>
54 #endif
55 
56 #ifdef ANDROID
57 #include <jni.h>
58 #include "SDL_system.h"
59 
60 std::vector<std::pair<std::string, int> >* g_list = NULL;
61 
62 #define MAKE_ADD_DNS_SRV_RECORD_CALLBACK(x) JNIEXPORT void JNICALL Java_ ## x##_SuperTuxKartActivity_addDNSSrvRecords(JNIEnv* env, jobject this_obj, jstring name, jint weight)
63 #define ANDROID_ADD_DNS_SRV_RECORD_CALLBACK(PKG_NAME) MAKE_ADD_DNS_SRV_RECORD_CALLBACK(PKG_NAME)
64 
65 extern "C"
ANDROID_ADD_DNS_SRV_RECORD_CALLBACK(ANDROID_PACKAGE_CALLBACK_NAME)66 ANDROID_ADD_DNS_SRV_RECORD_CALLBACK(ANDROID_PACKAGE_CALLBACK_NAME)
67 {
68     if (!g_list || name == NULL)
69         return;
70     const uint16_t* utf16_text =
71         (const uint16_t*)env->GetStringChars(name, NULL);
72     if (utf16_text == NULL)
73         return;
74     const size_t str_len = env->GetStringLength(name);
75     std::string tmp;
76     utf8::unchecked::utf16to8(
77         utf16_text, utf16_text + str_len, std::back_inserter(tmp));
78     g_list->emplace_back(tmp, weight);
79     env->ReleaseStringChars(name, utf16_text);
80 }
81 
82 #endif
83 
84 NetworkConfig *NetworkConfig::m_network_config[PT_COUNT];
85 bool NetworkConfig::m_system_ipv4 = false;
86 bool NetworkConfig::m_system_ipv6 = false;
87 
88 /** Initialize detection of system IPv4 or IPv6 support. */
initSystemIP()89 void NetworkConfig::initSystemIP()
90 {
91     // It calls WSAStartup in enet, for the rest new Network function we don't
92     // need this because request manager runs curl_global_init which will do
93     // WSAStartup too
94     if (enet_initialize() != 0)
95     {
96         Log::error("NetworkConfig", "Could not initialize enet.");
97         return;
98     }
99     ENetAddress eaddr = {};
100     setIPv6Socket(0);
101     auto ipv4 = std::unique_ptr<Network>(new Network(1, 1, 0, 0, &eaddr));
102     setIPv6Socket(1);
103     auto ipv6 = std::unique_ptr<Network>(new Network(1, 1, 0, 0, &eaddr));
104     setIPv6Socket(0);
105     if (ipv4 && ipv4->getENetHost())
106         m_system_ipv4 = true;
107     if (ipv6 && ipv6->getENetHost())
108         m_system_ipv6 = true;
109     // If any 1 of them is missing set default network setting accordingly
110     if (!m_system_ipv4)
111     {
112         Log::warn("NetworkConfig", "System doesn't support IPv4");
113         if (m_system_ipv6)
114         {
115             UserConfigParams::m_ipv6_lan = true;
116             ServerConfig::m_ipv6_connection = true;
117         }
118     }
119     else if (!m_system_ipv6)
120     {
121         Log::warn("NetworkConfig", "System doesn't support IPv6");
122         UserConfigParams::m_ipv6_lan = false;
123         ServerConfig::m_ipv6_connection = false;
124     }
125     enet_deinitialize();
126 }   // initSystemIP
127 
128 /** \class NetworkConfig
129  *  This class is the interface between STK and the online code, particularly
130  *  STKHost. It stores all online related properties (e.g. if this is a server
131  *  or a host, name of the server, maximum number of players, ip address, ...).
132  *  They can either be set from the GUI code, or via the command line (for a
133  *  stand-alone server).
134  *  When STKHost is created, it takes all necessary information from this
135  *  instance.
136  */
137 // ============================================================================
138 /** Constructor.
139  */
NetworkConfig()140 NetworkConfig::NetworkConfig()
141 {
142     m_ip_type               = IP_NONE;
143     m_network_type          = NETWORK_NONE;
144     m_auto_connect          = false;
145     m_is_server             = false;
146     m_is_public_server      = false;
147     m_done_adding_network_players = false;
148     m_cur_user_id           = 0;
149     m_cur_user_token        = "";
150     m_client_port = 0;
151     m_joined_server_version = 0;
152     m_network_ai_instance = false;
153     m_state_frequency = 10;
154     m_nat64_prefix_data.fill(-1);
155     m_num_fixed_ai = 0;
156     m_tux_hitbox_addon = false;
157 }   // NetworkConfig
158 
159 // ----------------------------------------------------------------------------
160 /** Separated from constructor because this needs to be run after user config
161  *  is load.
162  */
initClientPort()163 void NetworkConfig::initClientPort()
164 {
165     m_client_port = UserConfigParams::m_random_client_port ?
166         0 : stk_config->m_client_port;
167 }   // initClientPort
168 
169 // ----------------------------------------------------------------------------
170 /** Set that this is not a networked game.
171  */
unsetNetworking()172 void NetworkConfig::unsetNetworking()
173 {
174     clearServerCapabilities();
175     m_network_type = NETWORK_NONE;
176     ServerConfig::m_private_server_password = "";
177 }   // unsetNetworking
178 
179 // ----------------------------------------------------------------------------
setUserDetails(std::shared_ptr<Online::XMLRequest> r,const std::string & name)180 void NetworkConfig::setUserDetails(std::shared_ptr<Online::XMLRequest> r,
181                                    const std::string& name)
182 {
183     assert(!m_cur_user_token.empty());
184     r->setApiURL(Online::API::USER_PATH, name);
185     r->addParameter("userid", m_cur_user_id);
186     r->addParameter("token", m_cur_user_token);
187 }   // setUserDetails
188 
189 // ----------------------------------------------------------------------------
setServerDetails(std::shared_ptr<Online::XMLRequest> r,const std::string & name)190 void NetworkConfig::setServerDetails(std::shared_ptr<Online::XMLRequest> r,
191                                      const std::string& name)
192 {
193     assert(!m_cur_user_token.empty());
194     r->setApiURL(Online::API::SERVER_PATH, name);
195     r->addParameter("userid", m_cur_user_id);
196     r->addParameter("token", m_cur_user_token);
197 }   // setServerDetails
198 
199 // ----------------------------------------------------------------------------
200 std::vector<GUIEngine::Screen*>
getResetScreens(bool lobby) const201     NetworkConfig::getResetScreens(bool lobby) const
202 {
203     if (lobby)
204     {
205         if (isWAN())
206         {
207             return
208                 {
209                     MainMenuScreen::getInstance(),
210                     OnlineScreen::getInstance(),
211                     OnlineProfileServers::getInstance(),
212                     NetworkingLobby::getInstance(),
213                     nullptr
214                 };
215         }
216         else
217         {
218             return
219                 {
220                     MainMenuScreen::getInstance(),
221                     OnlineScreen::getInstance(),
222                     OnlineLanScreen::getInstance(),
223                     NetworkingLobby::getInstance(),
224                     nullptr
225                 };
226         }
227     }
228     else
229     {
230         if (isWAN())
231         {
232             return
233                 {
234                     MainMenuScreen::getInstance(),
235                     OnlineScreen::getInstance(),
236                     OnlineProfileServers::getInstance(),
237                     nullptr
238                 };
239         }
240         else
241         {
242             return
243                 {
244                     MainMenuScreen::getInstance(),
245                     OnlineScreen::getInstance(),
246                     OnlineLanScreen::getInstance(),
247                     nullptr
248                 };
249         }
250     }
251 }   // getResetScreens
252 
253 // ----------------------------------------------------------------------------
254 /** Called before (re)starting network race, must be used before adding
255  *  split screen players. */
clearActivePlayersForClient() const256 void NetworkConfig::clearActivePlayersForClient() const
257 {
258     if (!isClient())
259         return;
260     StateManager::get()->resetActivePlayers();
261     if (input_manager)
262     {
263         input_manager->getDeviceManager()->setAssignMode(NO_ASSIGN);
264         input_manager->getDeviceManager()->setSinglePlayer(NULL);
265         input_manager->setMasterPlayerOnly(false);
266         input_manager->getDeviceManager()->clearLatestUsedDevice();
267     }
268 }   // clearActivePlayersForClient
269 
270 // ----------------------------------------------------------------------------
271 /** True when client needs to round the bodies phyiscal info for current
272  *  ticks, server doesn't as it will be done implictly in save state. */
roundValuesNow() const273 bool NetworkConfig::roundValuesNow() const
274 {
275     return isNetworking() && !isServer() && RewindManager::get()
276         ->shouldSaveState(World::getWorld()->getTicksSinceStart());
277 }   // roundValuesNow
278 
279 // ----------------------------------------------------------------------------
280 /** Use stun servers to detect current ip type.
281  */
detectIPType()282 void NetworkConfig::detectIPType()
283 {
284     if (UserConfigParams::m_default_ip_type != IP_NONE)
285     {
286         int ip_type = UserConfigParams::m_default_ip_type;
287         m_nat64_prefix.clear();
288         m_nat64_prefix_data.fill(-1);
289         m_ip_type.store((IPType)ip_type);
290         return;
291     }
292 #ifdef ENABLE_IPV6
293     if (!m_system_ipv4 || !m_system_ipv6)
294     {
295         // Don't test connection if only IPv4 or IPv6 system support
296         if (m_system_ipv4)
297             m_ip_type.store(IP_V4);
298         else if (m_system_ipv6)
299             m_ip_type.store(IP_V6);
300         return;
301     }
302 
303     ENetAddress eaddr = {};
304     // We don't need to result of stun, just to check if the socket can be
305     // used in ipv4 or ipv6
306     uint8_t stun_tansaction_id[16] = {};
307     BareNetworkString s = STKHost::getStunRequest(stun_tansaction_id);
308     setIPv6Socket(0);
309     auto ipv4 = std::unique_ptr<Network>(new Network(1, 1, 0, 0, &eaddr));
310     setIPv6Socket(1);
311     auto ipv6 = std::unique_ptr<Network>(new Network(1, 1, 0, 0, &eaddr));
312     setIPv6Socket(0);
313 
314     // This should only happen if system doesn't support all socket types
315     if (!ipv4->getENetHost() || !ipv6->getENetHost())
316         return;
317 
318     auto& stunv4_map = UserConfigParams::m_stun_servers_v4;
319     for (auto& s : getStunList(true/*ipv4*/))
320     {
321         if (s.second == 0)
322             stunv4_map.erase(s.first);
323         else if (stunv4_map.find(s.first) == stunv4_map.end())
324             stunv4_map[s.first] = 0;
325     }
326     if (stunv4_map.empty())
327         return;
328     auto ipv4_it = stunv4_map.begin();
329     int adv = StkTime::getMonoTimeMs() % stunv4_map.size();
330     std::advance(ipv4_it, adv);
331 
332     auto& stunv6_map = UserConfigParams::m_stun_servers;
333     for (auto& s : getStunList(false/*ipv4*/))
334     {
335         if (s.second == 0)
336             stunv6_map.erase(s.first);
337         else if (stunv6_map.find(s.first) == stunv6_map.end())
338             stunv6_map[s.first] = 0;
339     }
340     if (stunv6_map.empty())
341         return;
342     auto ipv6_it = stunv6_map.begin();
343     adv = StkTime::getMonoTimeMs() % stunv6_map.size();
344     std::advance(ipv6_it, adv);
345 
346     SocketAddress::g_ignore_error_message = true;
347     SocketAddress stun_v4(ipv4_it->first, 0/*port specified in addr*/,
348         AF_INET);
349     bool sent_ipv4 = false;
350     if (!stun_v4.isUnset() && stun_v4.getFamily() == AF_INET)
351     {
352         sendto(ipv4->getENetHost()->socket, s.getData(), s.size(), 0,
353             stun_v4.getSockaddr(), stun_v4.getSocklen());
354         sent_ipv4 = true;
355     }
356 
357     SocketAddress stun_v6(ipv6_it->first, 0/*port specified in addr*/,
358         AF_INET6);
359     bool sent_ipv6 = false;
360     if (!stun_v6.isUnset() && stun_v6.getFamily() == AF_INET6)
361     {
362         sendto(ipv6->getENetHost()->socket, s.getData(), s.size(), 0,
363             stun_v6.getSockaddr(), stun_v6.getSocklen());
364         sent_ipv6 = true;
365     }
366     SocketAddress::g_ignore_error_message = false;
367 
368     bool has_ipv4 = false;
369     bool has_ipv6 = false;
370 
371     ENetSocketSet socket_set;
372     ENET_SOCKETSET_EMPTY(socket_set);
373     ENET_SOCKETSET_ADD(socket_set, ipv4->getENetHost()->socket);
374     if (sent_ipv4)
375     {
376         // 1.5 second timeout
377         has_ipv4 = enet_socketset_select(
378             ipv4->getENetHost()->socket, &socket_set, NULL, 1500) > 0;
379     }
380 
381     ENET_SOCKETSET_EMPTY(socket_set);
382     ENET_SOCKETSET_ADD(socket_set, ipv6->getENetHost()->socket);
383     if (sent_ipv6 && enet_socketset_select(
384         ipv6->getENetHost()->socket, &socket_set, NULL, 1500) > 0)
385     {
386         has_ipv6 = true;
387         // For non dual stack IPv6 we try to get a NAT64 prefix to connect
388         // to IPv4 only servers
389         if (!has_ipv4)
390         {
391             // Detect NAT64 prefix by using ipv4only.arpa (RFC 7050)
392             m_nat64_prefix.clear();
393             m_nat64_prefix_data.fill(-1);
394             SocketAddress nat64("ipv4only.arpa", 0/*port*/, AF_INET6);
395             if (nat64.getFamily() == AF_INET6)
396             {
397                 // Remove last 4 bytes which is IPv4 format
398                 struct sockaddr_in6* in6 =
399                     (struct sockaddr_in6*)nat64.getSockaddr();
400                 uint8_t* byte = &(in6->sin6_addr.s6_addr[0]);
401                 byte[12] = 0;
402                 byte[13] = 0;
403                 byte[14] = 0;
404                 byte[15] = 0;
405                 m_nat64_prefix_data[0] = ((uint32_t)(byte[0]) << 8) | byte[1];
406                 m_nat64_prefix_data[1] = ((uint32_t)(byte[2]) << 8) | byte[3];
407                 m_nat64_prefix_data[2] = ((uint32_t)(byte[4]) << 8) | byte[5];
408                 m_nat64_prefix_data[3] = ((uint32_t)(byte[6]) << 8) | byte[7];
409                 m_nat64_prefix_data[4] = ((uint32_t)(byte[8]) << 8) | byte[9];
410                 m_nat64_prefix_data[5] = ((uint32_t)(byte[10]) << 8) | byte[11];
411                 m_nat64_prefix_data[6] = 0;
412                 m_nat64_prefix_data[7] = 0;
413                 m_nat64_prefix = getIPV6ReadableFromIn6(in6);
414             }
415         }
416     }
417 
418     if (has_ipv4 && has_ipv6)
419     {
420         Log::info("NetworkConfig", "System is dual stack network.");
421         m_nat64_prefix.clear();
422         m_nat64_prefix_data.fill(-1);
423         m_ip_type = IP_DUAL_STACK;
424     }
425     else if (has_ipv4)
426     {
427         Log::info("NetworkConfig", "System is IPv4 only.");
428         m_nat64_prefix.clear();
429         m_nat64_prefix_data.fill(-1);
430         m_ip_type = IP_V4;
431     }
432     else if (has_ipv6)
433     {
434         Log::info("NetworkConfig", "System is IPv6 only.");
435         if (m_nat64_prefix.empty())
436             m_ip_type = IP_V6;
437     }
438     else
439     {
440         Log::error("NetworkConfig", "Cannot detect network type using stun, "
441             "using previously detected type: %d", (int)m_ip_type.load());
442     }
443     if (has_ipv6)
444     {
445         if (!has_ipv4 && m_nat64_prefix.empty())
446         {
447             Log::warn("NetworkConfig", "NAT64 prefix not found, "
448                 "you may not be able to join any IPv4 only servers.");
449         }
450         if (!m_nat64_prefix.empty())
451         {
452             m_ip_type = IP_V6_NAT64;
453             Log::info("NetworkConfig",
454                 "NAT64 prefix is %s.", m_nat64_prefix.c_str());
455         }
456     }
457 #else
458     m_ip_type = IP_V4;
459 #endif
460 }   // detectIPType
461 
462 // ----------------------------------------------------------------------------
fillStunList(std::vector<std::pair<std::string,int>> * l,const std::string & dns)463 void NetworkConfig::fillStunList(std::vector<std::pair<std::string, int> >* l,
464                                  const std::string& dns)
465 {
466 #if defined(WIN32)
467     PDNS_RECORD dns_record = NULL;
468     DnsQuery(StringUtils::utf8ToWide(dns).c_str(), DNS_TYPE_SRV,
469         DNS_QUERY_STANDARD, NULL, &dns_record, NULL);
470     if (dns_record)
471     {
472         for (PDNS_RECORD curr = dns_record; curr; curr = curr->pNext)
473         {
474             if (curr->wType == DNS_TYPE_SRV)
475             {
476                 l->emplace_back(
477                     StringUtils::wideToUtf8(curr->Data.SRV.pNameTarget) +
478                     ":" + StringUtils::toString(curr->Data.SRV.wPort),
479                     curr->Data.SRV.wWeight);
480             }
481         }
482         DnsRecordListFree(dns_record, DnsFreeRecordListDeep);
483     }
484 
485 #elif defined(ANDROID)
486     JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
487     if (env == NULL)
488     {
489         Log::error("NetworkConfig",
490             "getDNSSrvRecords unable to SDL_AndroidGetJNIEnv.");
491         return;
492     }
493 
494     jobject native_activity = (jobject)SDL_AndroidGetActivity();
495     if (native_activity == NULL)
496     {
497         Log::error("NetworkConfig",
498             "getDNSSrvRecords unable to SDL_AndroidGetActivity.");
499         return;
500     }
501 
502     jclass class_native_activity = env->GetObjectClass(native_activity);
503     if (class_native_activity == NULL)
504     {
505         Log::error("NetworkConfig",
506             "getDNSSrvRecords unable to find object class.");
507         env->DeleteLocalRef(native_activity);
508         return;
509     }
510 
511     jmethodID method_id = env->GetMethodID(class_native_activity,
512         "getDNSSrvRecords", "(Ljava/lang/String;)V");
513 
514     if (method_id == NULL)
515     {
516         Log::error("NetworkConfig",
517             "getDNSSrvRecords unable to find method id.");
518         env->DeleteLocalRef(class_native_activity);
519         env->DeleteLocalRef(native_activity);
520         return;
521     }
522 
523     std::vector<uint16_t> jstr_data;
524     utf8::unchecked::utf8to16(
525         dns.c_str(), dns.c_str() + dns.size(), std::back_inserter(jstr_data));
526     jstring text =
527         env->NewString((const jchar*)jstr_data.data(), jstr_data.size());
528     if (text == NULL)
529     {
530         Log::error("NetworkConfig",
531             "Failed to create text for domain name.");
532         env->DeleteLocalRef(class_native_activity);
533         env->DeleteLocalRef(native_activity);
534         return;
535     }
536 
537     g_list = l;
538     env->CallVoidMethod(native_activity, method_id, text);
539     env->DeleteLocalRef(text);
540     env->DeleteLocalRef(class_native_activity);
541     env->DeleteLocalRef(native_activity);
542     g_list = NULL;
543 
544 #elif !defined(__CYGWIN__)
545 #define SRV_WEIGHT (RRFIXEDSZ+2)
546 #define SRV_PORT (RRFIXEDSZ+4)
547 #define SRV_SERVER (RRFIXEDSZ+6)
548 #define SRV_FIXEDSZ (RRFIXEDSZ+6)
549 
550     unsigned char response[512] = {};
551     int response_len = res_query(dns.c_str(), C_IN, T_SRV, response, 512);
552     if (response_len > 0)
553     {
554         HEADER* header = (HEADER*)response;
555         unsigned char* start = response + NS_HFIXEDSZ;
556 
557         if ((header->tc) || (response_len < NS_HFIXEDSZ))
558             return;
559 
560         if (header->rcode >= 1 && header->rcode <= 5)
561             return;
562 
563         int ancount = ntohs(header->ancount);
564         int qdcount = ntohs(header->qdcount);
565         if (ancount == 0)
566             return;
567 
568         if (ancount > NS_PACKETSZ)
569             return;
570 
571         for (int count = qdcount; count > 0; count--)
572         {
573             int str_len = dn_skipname(start, response + response_len);
574             start += str_len + NS_QFIXEDSZ;
575         }
576 
577         std::vector<unsigned char*> srv;
578         for (int count = ancount; count > 0; count--)
579         {
580             int str_len = dn_skipname(start, response + response_len);
581             start += str_len;
582             srv.push_back(start);
583             start += SRV_FIXEDSZ;
584             start += dn_skipname(start, response + response_len);
585         }
586 
587         for (unsigned i = 0; i < srv.size(); i++)
588         {
589             char server_name[512] = {};
590             if (ns_name_ntop(srv[i] + SRV_SERVER, server_name, 512) < 0)
591                 continue;
592             uint16_t port = ns_get16(srv[i] + SRV_PORT);
593             uint16_t weight = ns_get16(srv[i] + SRV_WEIGHT);
594             l->emplace_back(std::string(server_name) + ":" +
595                 StringUtils::toString(port), weight);
596         }
597     }
598 #endif
599 }   // fillStunList
600 
601 // ----------------------------------------------------------------------------
602 const std::vector<std::pair<std::string, int> >&
getStunList(bool ipv4)603                                           NetworkConfig::getStunList(bool ipv4)
604 {
605     static std::vector<std::pair<std::string, int> > ipv4_list;
606     static std::vector<std::pair<std::string, int> > ipv6_list;
607     if (ipv4)
608     {
609         if (ipv4_list.empty())
610             NetworkConfig::fillStunList(&ipv4_list, stk_config->m_stun_ipv4);
611         return ipv4_list;
612     }
613     else
614     {
615         if (ipv6_list.empty())
616             NetworkConfig::fillStunList(&ipv6_list, stk_config->m_stun_ipv6);
617         return ipv6_list;
618     }
619 }   // getStunList
620