Bug 2355 - Quake 3 IPv6 support
Status: RESOLVED FIXED
Alias: None
Product: ioquake3
Classification: Unclassified
Component: Misc
Version: 1.33 SVN
Hardware: All Linux
: P2 enhancement
Assignee: Zachary J. Slater
QA Contact: ioquake3 bugzilla mailing list
URL: http://doli.ic.cz/ipv6/quake3/
Depends on:
Blocks:
 
Reported: 2005-08-31 07:44 EDT by Lubos Dolezel
Modified: 2008-04-12 13:24:55 EDT
3 users (show)

See Also:


Attachments
IPv6 patch (tar.bz2) (5.23 KB, application/x-bzip2)
2005-08-31 07:45 EDT, Lubos Dolezel
Same patch, updated for latest subversion revision... (13.24 KB, patch)
2005-08-31 22:17 EDT, Ryan C. Gordon
Patch with multicast based on the first. (50.25 KB, patch)
2005-12-08 12:26 EST, JF Tremblay
Give up ipv6 and continue when inet6 socket family is not available (278 bytes, patch)
2005-12-09 14:07 EST, Patryk Szczyglowski

Description Lubos Dolezel 2005-08-31 07:44:27 EDT
I have created IPv6 support for Quake 3. If you compile the code with -
DENABLE_IPV6 a "multistack" Quake 3 is created (supports both IPv4 and IPv6). 
Otherwise only IPv4 is supported.

I am a Linux developer - that means only Unix net code is patched. Someone 
should write a patch for Windows too.

I think that this patch should be tested first as there might be bugs.

Patch supports TCPv6 ports in three variants:
1) 3ffe::abca:5::27960
2) 3ffe::abca:5@27960
3) [3ffe::abca:5]:27960

Patch should support local IPv6 network scanning (untested!).

There is currently one limitation. IPv6 banning is not supported (g_svcmds.c). I 
can write the patch later if required.
Comment 1 Lubos Dolezel 2005-08-31 07:45:38 EDT
Created attachment 772 [details]
IPv6 patch (tar.bz2)
Comment 2 Lubos Dolezel 2005-08-31 09:46:34 EDT
I have done some minor code cleanup... you can get the updated file here:
http://doli.ic.cz/ipv6/quake3/quake3-ipv6.tar.bz2

(I want to avoid file reposting)
Comment 3 Zachary J. Slater 2005-08-31 22:11:51 EDT
The unix_net.c patch doesn't apply cleanly, if you can clean it up soonish, I
can CI this and get it over with.
Comment 4 Ryan C. Gordon 2005-08-31 22:14:10 EDT
I cleaned up the patch issue, but:

In code/qcommon/net_chan.c, your patch has this:

-       // inet_addr returns this if out of range
-       if ( a->ip[0] == 255 && a->ip[1] == 255 && a->ip[2] == 255 && a->ip[3]
== 255 ) {
-               a->type = NA_BAD;
-               return qfalse;
-       }
-

...is that safe to remove in the ipv4 case?

--ryan.

Comment 5 Ryan C. Gordon 2005-08-31 22:17:45 EDT
Created attachment 774 [details]
Same patch, updated for latest subversion revision...


Here's the same patch, just changed to apply cleanly to latest revision.

Just need an answer on that one chunk of code...

--ryan.
Comment 6 Lubos Dolezel 2005-09-01 05:01:27 EDT
Well, it shouldn't be removed because of Windows code. Windows code still uses
obsolete inet_addr() which returns 0xffffffff on failure and I don't have enough
energy to fight with that ugly win_net.c code (ugly when compared to unix_net.c
code).

And you can remove this from patch (both in NET_StringToAdr):
Com_Printf("address: %s\n", base);
Com_Printf("address2: %s\n", base);
I've added them when I was debugging...

I haven't mentioned another limitation of my IPv6 implementation yet. Connect
will fail if you use Multiplayer-Specify dialog and use port shorter than 5
characters. This has a simple reason - some (probably) script creates an address
by appending ":port" to IP address and then calls CL_Connect_f().

So the program must make a guess: is that ":xxxx" at the end of address port or
a portion of IPv6 address? When there are >4 characters it is definitely port.
Default Q3 port is 5 chars long so it shouldn't bother many people. They can
still use "/connect" in console for shorter ports...
Comment 7 Lubos Dolezel 2005-09-01 05:34:06 EDT
Another small thing in Sys_IsLANAddress():

if(adr.ip6[0] == 0xfe && adr.ip6[1] == 0x80)

should be 

if(adr.ip6[0] == 0xfe && (adr.ip6[1] & 0xc0) == 0x80)

I have overlooked the rank size while reading RFC. Local link scope is
fe80::/10, not fe80::/16. IPv6 ranks are real mess... :(
I hope that all problems are fixed now.
Comment 8 Daniel NAKATA 2005-09-13 06:09:45 EDT
"I haven't mentioned another limitation of my IPv6 implementation yet. Connect  
will fail if you use Multiplayer-Specify dialog and use port shorter than 5  
characters. This has a simple reason - some (probably) script creates an  
address by appending ":port" to IP address and then calls CL_Connect_f()."  
  
I have a little fix for that in my IPv6 patch, which uses '[]' encapsulation  
for IPv6 addresses, the same way browsers and scp do it;  
  
/connect [2001:470:1f00:488:1::1]:2781  
  
would then work.  The only place this really matters (as far as I can tell so 
far) is Sys_StringToSockaddr. 
  
I'm not sure how to 'attach', so, here's the routine; 
 
--SNIP-- 
qboolean        Sys_StringToSockaddr (const char *s, struct sockaddr_storage 
*sadr) { 
        char    copy[128]; 
        char    *addrs, *space; 
        char    *ports = NULL; 
        int     err; 
        struct addrinfo hints; 
        struct addrinfo *resultp; 
 
        memset (&hints,0, sizeof(hints)); 
        hints.ai_socktype = SOCK_DGRAM; 
        hints.ai_family = PF_UNSPEC; 
 
        strcpy (copy, s); 
        addrs = space = copy; 
        if (*addrs == '[') { 
                addrs++; 
                for (; *space && *space != ']'; space++); 
                if (!*space) { 
                        Com_Printf ("NET_StringToSockaddr: invalid IPv6 address 
%s\n", s); 
                        return 0; 
                } 
                *space++ = '\0'; 
        } 
 
        for (; *space; space++) { 
                if (*space == ':') { 
                        *space = '\0'; 
                        ports = space + 1; 
                } 
        } 
 
        if ((err = getaddrinfo (addrs, ports, &hints, &resultp))) { 
                // Error 
                Com_Printf ("NET_StringToSockaddr: string %s:\n%s\n", s, 
gai_strerror(err)); 
                return 0; 
        } 
 
        switch (resultp->ai_family) { 
                case AF_INET: 
                        // convert to ipv4 addr 
                        memset (sadr, 0, sizeof (struct sockaddr_storage)); 
                        memcpy (sadr, resultp->ai_addr, resultp->ai_addrlen); 
                        break; 
                case AF_INET6: 
                        // convert to ipv6 addr 
                        memset (sadr, 0, sizeof (struct sockaddr_storage)); 
                        memcpy (sadr, resultp->ai_addr, resultp->ai_addrlen); 
                        break; 
                default: 
                        Com_Printf 
                                ("NET_StringToSockaddr: string %s:\nprotocol 
family %d not supported\n", 
                                s, resultp->ai_family); 
                        return 0; 
        } 
 
        return qtrue; 
} 
--SNIP-- 
Comment 9 Daniel NAKATA 2005-09-13 06:18:07 EDT
wow, i missed this:  
  
"Patch supports TCPv6 ports in three variants: 
1) 3ffe::abca:5::27960 
2) 3ffe::abca:5@27960 
3) [3ffe::abca:5]:27960" 
 
are you sure 1 and 2 are good ideas?  i think if we stick with 3, the standard, 
we should be fine. 
 
and in the case of 1, we assume default port and don't check for one, if we 
even allow it? 
Comment 10 Lubos Dolezel 2005-09-13 11:29:04 EDT
"are you sure 1 and 2 are good ideas?"

Well, I don't know whether are they standard or not but I've seen them...

"and in the case of 1, we assume default port and don't check for one, if we 
even allow it?"
Yes, we check for the port - we don't assume anything:

NET_StringToAdr(...)
{
//...

if(*(port-1) == ':' && strstr(base, "::") != port-1) // there are more ::
{
	// "3ffe:80ee:3309::1::2222" -> "3ffe:80ee:3309::1\0:2222"
	*(port-1) = 0; // zero the first : in the last ::
}

// ...

// "port" still points to the ':'

if(port)
{
	// "3ffe:80ee:3309::1\0:2222" -> "3ffe:80ee:3309::1\0\02222"
	//                     ^      ->                       ^
	*port = 0;
	port++; // "port" now points to the port
}
// convert port to integer....


"I have a little fix for that in my IPv6 patch..."
/connect [....]:port should work anyway...

But I have found a small problem in my code. Site-local addresses are treated as
global addresses.

in Sys_IsLANAddress():

if(adr.ip6[0] == 0xfe && (adr.ip6[1] & 0xc0) == 0x80)
--should be--
if(adr.ip6[0] == 0xfe && ( (adr.ip6[1] & 0xc0) == 0x80 || (adr.ip6[1] & 0xc0) ==
0xc0))
Comment 11 Daniel NAKATA 2005-09-15 01:53:08 EDT
Okay, something I've found in my patch which may incarnate in your patch as 
well just by glancing through net_chan.c ~line 750, if no port is specified, 
will it use the last quad as the port? 
 
For example, /connect 2001:470:1f00:488:1::102 
Comment 12 Lubos Dolezel 2005-09-15 10:10:51 EDT
"if no port is specified, 
will it use the last quad as the port?"

Nope. This combination finds out whether there are more '::' in the string.
Notice the strRchr()...

port = strrchr( base, ':' ); // find last ':'
// ...
// if (port-1) points to the last '::' compare it to the address of first '::'
if(*(port-1) == ':' && strstr(base, "::") != port-1) // there are more ::
Comment 13 Patryk Szczyglowski 2005-11-08 06:21:04 EST
Here is simmilar project:
http://www.hexago.com/index.php?pgID=52
Comment 14 Lubos Dolezel 2005-11-08 10:56:37 EST
Those bastards have copied and edited my code...they wrote the Win32 part, but the most of the rest is my code.

Have a look in their patch for this string:

+#endif // well, we can use getnameinfo for IPv4 too...but let's leave it as it is (for sure)

I wrote this note! Not they...

- NET_GetLocalAddress in unix_net.c hasn't been ported yet.
What a big surprise...I haven't ported it too...

They could at least say that this isn't fully their work and not just "Hexago ©2004"
Comment 15 Patryk Szczyglowski 2005-11-08 18:35:34 EST
(In reply to comment #14)
> Those bastards have copied and edited my code...they wrote the Win32 part, but
> the most of the rest is my code.
[...]
> 
> They could at least say that this isn't fully their work and not just "Hexago
> ©2004"
> 

Have a look at http://www.hexago.com/docs/doc_20051018-37.pdf:
"Thanks to Lubos Dolezel for providing a first patch for IPv6
support and to Florent Parent for his help with the port."

Anyway, I have a patch for their patch ;)
Comment 16 JF Tremblay 2005-12-08 12:11:59 EST
(In reply to comment #15)
> (In reply to comment #14)
> > Those bastards have copied and edited my code...they wrote the Win32 part, but
> > the most of the rest is my code.
> [...]
> > 
> > They could at least say that this isn't fully their work and not just "Hexago
> > ©2004"
> > 
> 
> Have a look at http://www.hexago.com/docs/doc_20051018-37.pdf:
> "Thanks to Lubos Dolezel for providing a first patch for IPv6
> support and to Florent Parent for his help with the port."
> 
> Anyway, I have a patch for their patch ;)

Sorry guys, it completely got out of my mind to post the patch here. Patryk, did you really produce a new patch or I should post mine here? Anyway, I should update it from the lastest svn. 

There's still some work to put on this to have it handle multicast properly. I still get some errors from sendto when sending multicast on Windows, even if the join to the group seems to work. 

Lubos, I apologize for not mentioning you are the original author of the patch on the page, it must have been lost in the copy-paste of the text. I intended mention it, as it was in the pdf doc. I'll add it to the page as soon as I get a chance. 


Comment 17 JF Tremblay 2005-12-08 12:26:29 EST
Created attachment 822 [details]
Patch with multicast based on the first.
Comment 18 Patryk Szczyglowski 2005-12-09 14:06:13 EST
(In reply to comment #16)
> Sorry guys, it completely got out of my mind to post the patch here. Patryk,
> did you really produce a new patch or I should post mine here? Anyway, I should
> update it from the lastest svn. 

My fix is a litlle one-liner for a condition, where ipv6 support is not compiled in linux kernel. It bails out on "socket family not supported". I made him to simply gave up after some tries and continue with ipv4 socket only. Seems to work :)
Comment 19 Patryk Szczyglowski 2005-12-09 14:07:53 EST
Created attachment 823 [details]
Give up ipv6 and continue when inet6 socket family is not available
Comment 20 Ryan C. Gordon 2007-05-21 11:21:53 EDT
Setting a QA contact on all ioquake3 bugs, even resolved ones. Sorry if you get a flood of email from this, it should only happen once. Apologies for the incovenience.

--ryan.

Comment 21 Tim Angus 2007-08-23 11:43:18 EDT
This is likely to need to be fiddled with after bug #3316 is addressed.
Comment 22 Thilo Schulz 2008-04-12 13:24:55 EDT
IPv6 is now fully supported by ioquake3.