Skip to content

Wiimmfi

Wiimmfi replaces the Nintendo Wi-Fi Connection service. A console reaches it by using the Wiimmfi resolver at 95.217.77.181 as its DNS server. The resolver answers the Nintendo host names with Wiimmfi addresses and the game speaks the unchanged GameSpy protocols to those servers. This page describes the traffic Mario Kart Wii (RMCE, IOS36) exchanges with the service. The game reaches the network through the IOS socket service.

Name resolution

Host name Answer
gpcm.gs.nintendowifi.net 95.217.77.151
gpsp.gs.nintendowifi.net 95.217.77.151
mariokartwii.master.gs.nintendowifi.net 95.217.77.181
naswii.nintendowifi.net 78.46.231.155
mariokartwii.sake.gs.nintendowifi.net 78.46.231.155
gamestats.gs.nintendowifi.net 195.201.236.139
gamestats2.gs.nintendowifi.net 195.201.236.139
wiimmfi.de 95.217.77.151
ca.nas.wiimmfi.de 188.34.177.217
main.nas.wiimmfi.de 188.34.177.217
mariokartwii.available.gs.nintendowifi.net NXDOMAIN (response code 3)

These addresses can change. The availability host name has no record, so the GameSpy availability check never receives a reply. The game retries the lookup a few times and then continues with the login.

When the same query is repeated within a few tens of milliseconds, the resolver answers with the truncated flag set. IOS then retries the query over TCP port 53 of its configured DNS server and uses that answer.

Login

The game logs in through the following connections, in this order. Each connection goes to the address its host name resolves to in the table above.

  1. An HTTPS (TCP port 443) authentication exchange with naswii.nintendowifi.net. It returns the authtoken used in the next step.
  2. A GameSpy Presence Connection Manager (GPCM) login on TCP port 29900. The server opens with a challenge, the client logs in with the authtoken and the server accepts with a session key. The client then sends its status and updates its profile.

    server: \lc\1\challenge\<challenge>\id\1\final\
    client: \login\challenge\<client challenge>\authtoken\NDS/<profile id>/...\partnerid\11\response\<md5>\firewall\1\port\0\productid\11059\gamename\mariokartwii\namespaceid\16\sdkrevision\3\quiet\0\id\1\final\
    server: \lc\2\sesskey\<session key>\proof\<md5>\userid\<id>\profileid\<id>\uniquenick\<nick>\lt\<login ticket>\id\1\final\
    client: \status\1\sesskey\<session key>\statstring\/SCM/1/SCN/0/VER/90\locstring\final\
    client: \updatepro\sesskey\<session key>\firstname\Wii:<console user id>@RMCE\partnerid\11\final\
    
  3. A GameSpy Presence Search Player (GPSP) connection on TCP port 29901, used for \otherslist\ lookups of friend profiles.

  4. A GameSpy Query and Reporting 2 (QR2) heartbeat from the game's UDP socket to the master server on UDP port 27900. The game sends a 258 byte heartbeat with the server keys, the server answers with a 36 byte challenge, the game returns a 42 byte response and the server acknowledges with 15 bytes.
  5. An HTTPS exchange with mariokartwii.sake.gs.nintendowifi.net and a second one with naswii.nintendowifi.net. The game then opens TCP port 443 on wiimmfi.de. Nothing accepts the connection and the game continues after its connect timeout.

Server message after the heartbeat

About five seconds after the heartbeat acknowledgement, the master server sends a 3213 byte UDP datagram from port 27900 to the game socket that sent the heartbeat. It is a QR2 client message consisting of the bytes FE FD 06, a 4 byte key and a message body that contains PowerPC code and a Yaz0 block. The server repeats the datagram every three seconds until the game answers on the same socket with a 17 byte and a 159 byte datagram.

On a link with a 1500 byte MTU the datagram arrives as three IPv4 fragments with 1480, 1480 and 253 byte payloads. IOS reassembles them before delivering the datagram to the socket. A game that never receives the complete datagram never answers. It stays logged in but never enters a race or friend room.

Friend registration

For every registered friend code the game sends this GPCM message:

\addbuddy\sesskey\<session key>\newprofileid\<friend profile id>\reason\final\

When the friend has registered this console as well, the server answers with the friend's own request. While the friend is online, it also sends the friend's status with their public address and port.

\bm\4\f\<friend profile id>\date\<unix time>\msg\final\
\bm\100\f\<friend profile id>\msg\|s|1|ss|<statstring>|ls|<locstring>|ip|<decimal IPv4>|p|<port>|qm|0\final\

The game then requests the friend's profile over GPCM and sends a GPSP \otherslist\ query for the same profile.

client: \getprofile\sesskey\<session key>\profileid\<friend profile id>\id\<n>\final\
server: \pi\profileid\...\nick\...\uniquenick\...\final\

The first time the player enters Worldwide, Regional or Find a Friend after the server message has arrived, the game shows a three page Wiimmfi notice and a dialog with the choices Permit and Prohibit. Permit makes the game resolve ca.nas.wiimmfi.de and main.nas.wiimmfi.de. It then opens HTTP (TCP port 80) and HTTPS (TCP port 443) connections to them and logs into GPCM and GPSP again. During this step the patched code reads the Broadway chip ID registers ECID_U, ECID_M and ECID_L (SPR 924 to 926).

Afterwards the server sends room status over the GPCM connection in these forms:

\wiimmfi\status\pid\<profile id>\room\<room id>\region\<n>\np\<n>\name1\<base64>\name2\status\<n>\ol_status\<n>\ol_role\<n>\ol_slot\<n>\hs\<a>,<b>\time\<unix time>\final\
\wiimmfi\clear\pid\<profile id>\final\

Matchmaking

While searching, Worldwide matchmaking repeatedly queries the server browser on TCP port 28910 of the GPCM host. NAT negotiation runs from the game's UDP socket to port 27901 on 95.217.77.151, 78.46.231.155 and 188.34.177.217. Their replies arrive on the same socket and all three servers must see the same public mapping of it. Peers then send UDP directly to the game socket, so the mapping must accept datagrams from endpoints the socket has not yet sent to.