Merge branch 'ipv6' into 'next'

Fix IPv6

See merge request STJr/SRB2!1612
This commit is contained in:
sphere 2023-06-12 23:43:46 +00:00
commit c2c27bf356
7 changed files with 122 additions and 65 deletions

View file

@ -1318,9 +1318,9 @@ static boolean CL_SendJoin(void)
static INT32 FindRejoinerNum(SINT8 node)
{
char strippednodeaddress[64];
char addressbuffer[64];
const char *nodeaddress;
char *port;
const char *strippednodeaddress;
INT32 i;
// Make sure there is no dead dress before proceeding to the stripping
@ -1331,10 +1331,8 @@ static INT32 FindRejoinerNum(SINT8 node)
return -1;
// Strip the address of its port
strcpy(strippednodeaddress, nodeaddress);
port = strchr(strippednodeaddress, ':');
if (port)
*port = '\0';
strcpy(addressbuffer, nodeaddress);
strippednodeaddress = I_NetSplitAddress(addressbuffer, NULL);
// Check if any player matches the stripped address
for (i = 0; i < MAXPLAYERS; i++)
@ -3771,14 +3769,13 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
if (server && I_GetNodeAddress)
{
char addressbuffer[64];
const char *address = I_GetNodeAddress(node);
char *port = NULL;
if (address) // MI: fix msvcrt.dll!_mbscat crash?
{
strcpy(playeraddress[newplayernum], address);
port = strchr(playeraddress[newplayernum], ':');
if (port)
*port = '\0';
strcpy(addressbuffer, address);
strcpy(playeraddress[newplayernum],
I_NetSplitAddress(addressbuffer, NULL));
}
}
}

View file

@ -1207,26 +1207,32 @@ static void Internal_FreeNodenum(INT32 nodenum)
(void)nodenum;
}
char *I_NetSplitAddress(char *host, char **port)
{
boolean v4 = (strchr(host, '.') != NULL);
host = strtok(host, v4 ? ":" : "[]");
if (port)
*port = strtok(NULL, ":");
return host;
}
SINT8 I_NetMakeNode(const char *hostname)
{
SINT8 newnode = -1;
if (I_NetMakeNodewPort)
{
char *localhostname = strdup(hostname);
char *t = localhostname;
const char *port;
char *port;
if (!localhostname)
return newnode;
// retrieve portnum from address!
strtok(localhostname, ":");
port = strtok(NULL, ":");
hostname = I_NetSplitAddress(localhostname, &port);
// remove the port in the hostname as we've it already
while ((*t != ':') && (*t != '\0'))
t++;
*t = '\0';
newnode = I_NetMakeNodewPort(localhostname, port);
newnode = I_NetMakeNodewPort(hostname, port);
free(localhostname);
}
return newnode;

View file

@ -216,7 +216,11 @@ HMS_connect (const char *format, ...)
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
#ifndef NO_IPV6
if (M_CheckParm("-noipv6"))
#endif
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, cv_masterserver_timeout.value);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HMS_on_read);

View file

@ -109,6 +109,17 @@ extern boolean (*I_NetCanSend)(void);
*/
extern void (*I_NetFreeNodenum)(INT32 nodenum);
/**
\brief split a string into address and port
\param address string to split
\param port double pointer to hold port component (optional)
\return address component
*/
extern char *I_NetSplitAddress(char *address, char **port);
/** \brief open a connection with specified address
\param address address to connect to

View file

@ -340,8 +340,14 @@ static inline void I_UPnP_rem(const char *port, const char * servicetype)
static const char *SOCK_AddrToStr(mysockaddr_t *sk)
{
static char s[64]; // 255.255.255.255:65535 or IPv6:65535
static char s[64]; // 255.255.255.255:65535 or
// [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535
#ifdef HAVE_NTOP
#ifdef HAVE_IPV6
int v6 = (sk->any.sa_family == AF_INET6);
#else
int v6 = 0;
#endif
void *addr;
if(sk->any.sa_family == AF_INET)
@ -355,14 +361,21 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk)
if(addr == NULL)
sprintf(s, "No address");
else if(inet_ntop(sk->any.sa_family, addr, s, sizeof (s)) == NULL)
else if(inet_ntop(sk->any.sa_family, addr, &s[v6], sizeof (s) - v6) == NULL)
sprintf(s, "Unknown family type, error #%u", errno);
#ifdef HAVE_IPV6
else if(sk->any.sa_family == AF_INET6 && sk->ip6.sin6_port != 0)
strcat(s, va(":%d", ntohs(sk->ip6.sin6_port)));
else if(sk->any.sa_family == AF_INET6)
{
s[0] = '[';
strcat(s, "]");
if (sk->ip6.sin6_port != 0)
strcat(s, va(":%d", ntohs(sk->ip6.sin6_port)));
}
#endif
else if(sk->any.sa_family == AF_INET && sk->ip4.sin_port != 0)
strcat(s, va(":%d", ntohs(sk->ip4.sin_port)));
#else
if (sk->any.sa_family == AF_INET)
{
@ -427,7 +440,7 @@ static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask)
&& (b->ip4.sin_port == 0 || (a->ip4.sin_port == b->ip4.sin_port));
#ifdef HAVE_IPV6
else if (b->any.sa_family == AF_INET6)
return memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, sizeof(b->ip6.sin6_addr))
return !memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, sizeof(b->ip6.sin6_addr))
&& (b->ip6.sin6_port == 0 || (a->ip6.sin6_port == b->ip6.sin6_port));
#endif
else
@ -735,8 +748,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
unsigned long trueval = true;
#endif
mysockaddr_t straddr;
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
socklen_t len = sizeof(straddr);
if (s == (SOCKET_TYPE)ERRSOCKET)
return (SOCKET_TYPE)ERRSOCKET;
@ -754,14 +766,12 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
}
#endif
straddr.any = *addr;
memcpy(&straddr, addr, addrlen);
I_OutputMsg("Binding to %s\n", SOCK_AddrToStr(&straddr));
if (family == AF_INET)
{
mysockaddr_t tmpaddr;
tmpaddr.any = *addr ;
if (tmpaddr.ip4.sin_addr.s_addr == htonl(INADDR_ANY))
if (straddr.ip4.sin_addr.s_addr == htonl(INADDR_ANY))
{
opt = true;
opts = (socklen_t)sizeof(opt);
@ -778,7 +788,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
#ifdef HAVE_IPV6
else if (family == AF_INET6)
{
if (memcmp(addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL
if (memcmp(&straddr.ip6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL
{
opt = true;
opts = (socklen_t)sizeof(opt);
@ -788,7 +798,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
// make it IPv6 ony
opt = true;
opts = (socklen_t)sizeof(opt);
if (setsockopt(s, SOL_SOCKET, IPV6_V6ONLY, (char *)&opt, opts))
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&opt, opts))
{
CONS_Alert(CONS_WARNING, M_GetText("Could not limit IPv6 bind\n")); // I do not care anymore
}
@ -830,10 +840,17 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10);
}
if (getsockname(s, (struct sockaddr *)&sin, &len) == -1)
if (getsockname(s, &straddr.any, &len) == -1)
CONS_Alert(CONS_WARNING, M_GetText("Failed to get port number\n"));
else
current_port = (UINT16)ntohs(sin.sin_port);
{
if (family == AF_INET)
current_port = (UINT16)ntohs(straddr.ip4.sin_port);
#ifdef HAVE_IPV6
else if (family == AF_INET6)
current_port = (UINT16)ntohs(straddr.ip6.sin6_port);
#endif
}
return s;
}
@ -844,7 +861,7 @@ static boolean UDP_Socket(void)
struct my_addrinfo *ai, *runp, hints;
int gaie;
#ifdef HAVE_IPV6
const INT32 b_ipv6 = M_CheckParm("-ipv6");
const INT32 b_ipv6 = !M_CheckParm("-noipv6");
#endif
const char *serv;
@ -1156,6 +1173,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
SINT8 newnode = -1;
struct my_addrinfo *ai = NULL, *runp, hints;
int gaie;
size_t i;
if (!port || !port[0])
port = DEFAULTPORT;
@ -1183,13 +1201,24 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
while (runp != NULL)
{
// find ip of the server
if (sendto(mysockets[0], NULL, 0, 0, runp->ai_addr, runp->ai_addrlen) == 0)
// test ip address of server
for (i = 0; i < mysocketses; ++i)
{
memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen);
break;
/* sendto tests that there is a network to this
address */
if (runp->ai_addr->sa_family == myfamily[i] &&
sendto(mysockets[i], NULL, 0, 0,
runp->ai_addr, runp->ai_addrlen) == 0)
{
memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen);
break;
}
}
runp = runp->ai_next;
if (i < mysocketses)
runp = runp->ai_next;
else
break;
}
I_freeaddrinfo(ai);
return newnode;

View file

@ -975,7 +975,7 @@ static menuitem_t MP_MainMenu[] =
{
{IT_HEADER, NULL, "Join a game", NULL, 0},
{IT_STRING|IT_CALL, NULL, "Server browser...", M_ConnectMenuModChecks, 12},
{IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 22},
{IT_STRING|IT_KEYHANDLER, NULL, "Specify server address:", M_HandleConnectIP, 22},
{IT_HEADER, NULL, "Host a game", NULL, 54},
{IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 66},
{IT_STRING|IT_CALL, NULL, "Splitscreen...", M_StartSplitServerMenu, 76},
@ -11738,35 +11738,19 @@ static void M_StartServerMenu(INT32 choice)
#define CONNIP_LEN 128
static char setupm_ip[CONNIP_LEN];
#define DOTS "... "
// Draw the funky Connect IP menu. Tails 11-19-2002
// So much work for such a little thing!
static void M_DrawMPMainMenu(void)
static void M_DrawConnectIP(void)
{
INT32 x = currentMenu->x;
INT32 y = currentMenu->y;
INT32 y = currentMenu->y + 22;
const INT32 boxwidth = /*16*8 + 6*/ (BASEVIDWIDTH - 2*(x+5));
const INT32 maxstrwidth = boxwidth - 5;
char *drawnstr = malloc(sizeof(setupm_ip));
char *drawnstr_orig = drawnstr;
boolean drawthin, shorten = false;
// use generic drawer for cursor, items and title
M_DrawGenericMenu();
V_DrawRightAlignedString(BASEVIDWIDTH-x, y+66,
((itemOn == 4) ? V_YELLOWMAP : 0), va("(2-%d players)", MAXPLAYERS));
V_DrawRightAlignedString(BASEVIDWIDTH-x, y+76,
((itemOn == 5) ? V_YELLOWMAP : 0), "(2 players)");
V_DrawRightAlignedString(BASEVIDWIDTH-x, y+116,
((itemOn == 8) ? V_YELLOWMAP : 0), "(splitscreen)");
y += 22;
V_DrawFill(x+5, y+4+5, boxwidth, 8+6, 159);
strcpy(drawnstr, setupm_ip);
@ -11814,6 +11798,28 @@ static void M_DrawMPMainMenu(void)
free(drawnstr_orig);
}
// Draw the funky Connect IP menu. Tails 11-19-2002
// So much work for such a little thing!
static void M_DrawMPMainMenu(void)
{
INT32 x = currentMenu->x;
INT32 y = currentMenu->y;
// use generic drawer for cursor, items and title
M_DrawGenericMenu();
V_DrawRightAlignedString(BASEVIDWIDTH-x, y+66,
((itemOn == 4) ? V_YELLOWMAP : 0), va("(2-%d players)", MAXPLAYERS));
V_DrawRightAlignedString(BASEVIDWIDTH-x, y+76,
((itemOn == 5) ? V_YELLOWMAP : 0), "(2 players)");
V_DrawRightAlignedString(BASEVIDWIDTH-x, y+116,
((itemOn == 8) ? V_YELLOWMAP : 0), "(splitscreen)");
M_DrawConnectIP();
}
#undef DOTS
// Tails 11-19-2002
@ -11951,7 +11957,11 @@ static void M_HandleConnectIP(INT32 choice)
break;
// Rudimentary number and period enforcing - also allows letters so hostnames can be used instead
if ((choice >= '-' && choice <= ':') || (choice >= 'A' && choice <= 'Z') || (choice >= 'a' && choice <= 'z'))
// and square brackets for RFC 2732 IPv6 addresses
if ((choice >= '-' && choice <= ':') ||
(choice == '[' || choice == ']') ||
(choice >= 'A' && choice <= 'Z') ||
(choice >= 'a' && choice <= 'z'))
{
S_StartSound(NULL,sfx_menu1); // Tails
setupm_ip[l] = (char)choice;

View file

@ -33,7 +33,7 @@ typedef union
typedef struct
{
msg_header_t header;
char ip[16];
char ip[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
char port[8];
char name[32];
INT32 room;