From fb0db7b5ac48108a79f1c29996b2ed094a27bc91 Mon Sep 17 00:00:00 2001 From: luigi__ Date: Tue, 20 Apr 2010 16:38:21 +0000 Subject: [PATCH] Wifi: put in some parsing of DNS requests, and a warning when a DNS request to the WFC servers is detected, rather than just blocking any packet that contains "nintendowifi". The user has to confirm he wants to connect to WFC, otherwise SoftAP will deauthenticate (therefore breaking the connection). Note on the warning, for those who don't read warnings and just hit spacebar: I made the No button selected by default. If someone really wants to just block WFC, atleast we've got a more proper detector now... --- desmume/src/driver.h | 2 + desmume/src/wifi.cpp | 136 +++++++++++++++++++++++++---------- desmume/src/windows/main.cpp | 14 ++++ 3 files changed, 115 insertions(+), 37 deletions(-) diff --git a/desmume/src/driver.h b/desmume/src/driver.h index f6871dccf..95799eebc 100644 --- a/desmume/src/driver.h +++ b/desmume/src/driver.h @@ -49,6 +49,8 @@ public: virtual bool WIFI_SocketsAvailable() { return true; } virtual bool WIFI_PCapAvailable() { return false; } + virtual bool WIFI_WFCWarning() { return false; } + virtual int PCAP_findalldevs(pcap_if_t** alldevs, char* errbuf) { return -1; } virtual void PCAP_freealldevs(pcap_if_t* alldevs) {} virtual pcap_t* PCAP_open(const char* source, int snaplen, int flags, int readtimeout, char* errbuf) { return NULL; } diff --git a/desmume/src/wifi.cpp b/desmume/src/wifi.cpp index 34bd4413b..40d6ade52 100644 --- a/desmume/src/wifi.cpp +++ b/desmume/src/wifi.cpp @@ -53,6 +53,8 @@ const u8 BroadcastMAC[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +bool bWFCUserWarned = false; + #ifdef EXPERIMENTAL_WIFI_COMM socket_t wifi_socket = INVALID_SOCKET; sockaddr_t sendAddr; @@ -301,7 +303,7 @@ WifiComInterface* wifiCom; // 3: medium logging, for debugging, shows lots of stuff // 4: high logging, for debugging, shows almost everything, may slow down // 5: highest logging, for debugging, shows everything, may slow down a lot -#define WIFI_LOGGING_LEVEL 0 +#define WIFI_LOGGING_LEVEL 1 #define WIFI_LOG_USE_LOGC 0 @@ -653,6 +655,8 @@ bool WIFI_Init() if(wifiCom) wifiCom->Init(); + bWFCUserWarned = false; + return true; } @@ -679,6 +683,8 @@ void WIFI_Reset() wifiCom = wifiComs[CommonSettings.wifi.mode]; if(wifiCom) wifiCom->Reset(); + + bWFCUserWarned = false; } @@ -1898,6 +1904,20 @@ const u8 SoftAP_AssocResponse[] = { 0x01, 0x02, 0x82, 0x84, // Supported rates }; +// Deauthentication frame - sent if the user chose not to connect to WFC +const u8 SoftAP_DeauthFrame[] = { + /* 802.11 header */ + 0xC0, 0x00, // Frame control + 0x00, 0x00, // Duration ID + 0x00, 0x09, 0xBF, 0x12, 0x34, 0x56, // Receiver + SOFTAP_MACADDR, // Sender + SOFTAP_MACADDR, // BSSID + 0x00, 0x00, // Sequence control + + /* Frame body */ + 0x01, 0x00, // Reason code (is "unspecified" ok?) +}; + //todo - make a class to wrap this //todo - zeromus - inspect memory leak safety of all this static pcap_if_t * WIFI_index_device(pcap_if_t *alldevs, int index) @@ -1978,41 +1998,69 @@ void SoftAP_Reset() SoftAP.seqNum = 0; } -//I coded this up in a minute. is there a standard way of doing this or another function I can borrow? -static s32 searchmem(u8* data, u32 len, char* search) +static bool SoftAP_IsDNSRequestToWFC(u16 ethertype, u8* body) { - s32 i=0; - u32 searchLen = strlen(search); - if(len==0) return -1; - if(searchLen==0) return -1; - - for(;;) + // Check the various headers... + if (htons(ethertype) != 0x0800) return false; // EtherType: IP + if (body[0] != 0x45) return false; // Version: 4, header len: 5 + if (body[9] != 0x11) return false; // Protocol: UDP + if (htons(*(u16*)&body[22]) != 53) return false; // Dest. port: 53 (DNS) + if ((*(u16*)&body[28+2]) & 0x8000) return false; // must be a query + + // Analyze each question + u16 numquestions = htons(*(u16*)&body[28+4]); + u32 curoffset = 28+12; + for (u16 curquestion = 0; curquestion < numquestions; curquestion++) { - u32 j=0; - s32 snap = i; - for(;i> 2) & 0x3) { @@ -2114,6 +2160,22 @@ void SoftAP_SendPacket(u8 *packet, u32 len) if (SoftAP.status != APStatus_Associated) return; + if (!bWFCUserWarned && SoftAP_IsDNSRequestToWFC(*(u16*)&packet[30], &packet[32])) + { + // if the user chose not to connect to WFC + // disconnect them, and do not send the DNS packet + // otherwise just stop bothering them + if (driver->WIFI_WFCWarning()) + { + bWFCUserWarned = true; + } + else + { + SoftAP_Deauthenticate(); + return; + } + } + u32 epacketLen = ((len - 30 - 4) + 14); u8 epacket[2048]; diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index 05700a8e5..c62ed51b5 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -2099,6 +2099,20 @@ class WinDriver : public BaseDriver virtual bool WIFI_SocketsAvailable() { return bSocketsAvailable; } virtual bool WIFI_PCapAvailable() { return bWinPCapAvailable; } + virtual bool WIFI_WFCWarning() + { + return MessageBox(NULL, "You are going to connect to the Nintendo WFC servers.\n" + "\n" + "Please keep in mind that DeSmuME is not perfect\n" + "and connecting to WFC may cause unexpected problems\n" + "to the WFC servers, which Nintendo would not appreciate.\n" + "\n" + "Do you still want to connect?", + "DeSmuME - WFC warning", + MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING + ) == IDYES; + } + virtual int PCAP_findalldevs(pcap_if_t** alldevs, char* errbuf) { return _pcap_findalldevs(alldevs, errbuf); }