From 5421ea7b180b8cd2af36dcfd3173eb7847910e16 Mon Sep 17 00:00:00 2001
From: Rob Swindell <rob@synchro.net>
Date: Mon, 16 May 2022 20:20:27 -0700
Subject: [PATCH] Move IPv4/v6 address parse functions to netwrap.c

And create IPv4AddressToStr(), a wrapper for inet_ntop (or inet_ntoa, when inet_ntop isn't available).
---
 src/xpdev/ini_file.c | 55 ++++----------------------------
 src/xpdev/netwrap.c  | 75 ++++++++++++++++++++++++++++++++++----------
 src/xpdev/netwrap.h  |  3 ++
 3 files changed, 67 insertions(+), 66 deletions(-)

diff --git a/src/xpdev/ini_file.c b/src/xpdev/ini_file.c
index b9ccc5d237..e7ebb91937 100644
--- a/src/xpdev/ini_file.c
+++ b/src/xpdev/ini_file.c
@@ -27,6 +27,7 @@
 #include "datewrap.h"	/* ctime_r */
 #include "dirwrap.h"	/* fexist */
 #include "filewrap.h"	/* chsize */
+#include "netwrap.h"
 
 /* Maximum length of entire line, includes '\0' */
 #define INI_MAX_LINE_LEN		(INI_MAX_VALUE_LEN*2)
@@ -717,14 +718,8 @@ char* iniSetIpAddress(str_list_t* list, const char* section, const char* key, ui
 					,ini_style_t* style)
 {
 	char buf[128];
-	struct in_addr in_addr;
-	in_addr.s_addr=htonl(value);
 	return iniSetString(list, section, key,
-#if defined(__BORLANDC__) || defined(__MINGW32__)
-		inet_ntoa(in_addr), // deprecated function call
-#else
-		inet_ntop(AF_INET, &in_addr, buf, sizeof(buf)),
-#endif
+		IPv4AddressToStr(value, buf, sizeof(buf)),
 		style);
 }
 
@@ -1637,44 +1632,6 @@ int iniGetSocketOptions(str_list_t list, const char* section, SOCKET sock
 	return(0);
 }
 
-static uint32_t parseIpAddress(const char* value)
-{
-	uint32_t result = 0;
-
-	if(strchr(value,'.')==NULL)
-		return(strtol(value,NULL,0));
-
-#if defined(__BORLANDC__) || defined(__MINGW32__)
-	result = inet_addr(value); // deprecated function call
-#else
-	inet_pton(AF_INET, value, &result);
-#endif
-	return ntohl(result);
-}
-
-static struct in6_addr parseIp6Address(const char* value)
-{
-	struct addrinfo hints = {0};
-	struct addrinfo *res, *cur;
-	struct in6_addr ret = {{{0}}};
-
-	hints.ai_flags = AI_NUMERICHOST|AI_PASSIVE;
-	if(getaddrinfo(value, NULL, &hints, &res))
-		return ret;
-
-	for(cur = res; cur; cur++) {
-		if(cur->ai_addr->sa_family == AF_INET6)
-			break;
-	}
-	if(!cur) {
-		freeaddrinfo(res);
-		return ret;
-	}
-	memcpy(&ret, &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr, sizeof(ret));
-	freeaddrinfo(res);
-	return ret;
-}
-
 uint32_t iniReadIpAddress(FILE* fp, const char* section, const char* key, uint32_t deflt)
 {
 	char	buf[INI_MAX_VALUE_LEN];
@@ -1686,7 +1643,7 @@ uint32_t iniReadIpAddress(FILE* fp, const char* section, const char* key, uint32
 	if(*value==0)		/* blank value */
 		return(deflt);
 
-	return(parseIpAddress(value));
+	return parseIPv4Address(value);
 }
 
 struct in6_addr iniReadIp6Address(FILE* fp, const char* section, const char* key, struct in6_addr deflt)
@@ -1700,7 +1657,7 @@ struct in6_addr iniReadIp6Address(FILE* fp, const char* section, const char* key
 	if(*value==0)		/* blank value */
 		return(deflt);
 
-	return(parseIp6Address(value));
+	return parseIPv6Address(value);
 }
 
 uint32_t iniGetIpAddress(str_list_t list, const char* section, const char* key, uint32_t deflt)
@@ -1712,7 +1669,7 @@ uint32_t iniGetIpAddress(str_list_t list, const char* section, const char* key,
 	if(vp==NULL || *vp==0)		/* blank value or missing key */
 		return(deflt);
 
-	return(parseIpAddress(vp));
+	return parseIPv4Address(vp);
 }
 
 struct in6_addr iniGetIp6Address(str_list_t list, const char* section, const char* key, struct in6_addr deflt)
@@ -1724,7 +1681,7 @@ struct in6_addr iniGetIp6Address(str_list_t list, const char* section, const cha
 	if(vp==NULL || *vp==0)		/* blank value or missing key */
 		return(deflt);
 
-	return(parseIp6Address(vp));
+	return parseIPv6Address(vp);
 }
 
 #endif	/* !NO_SOCKET_SUPPORT */
diff --git a/src/xpdev/netwrap.c b/src/xpdev/netwrap.c
index 87a4ce3531..38bf3d7d79 100644
--- a/src/xpdev/netwrap.c
+++ b/src/xpdev/netwrap.c
@@ -1,9 +1,5 @@
-/* netwrap.c */
-
 /* Network related wrapper functions */
 
-/* $Id: netwrap.c,v 1.8 2019/07/24 04:21:42 rswindell Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -17,21 +13,9 @@
  * See the GNU Lesser General Public License for more details: lgpl.txt or	*
  * http://www.fsf.org/copyleft/lesser.html									*
  *																			*
- * Anonymous FTP access to the most recent released source is available at	*
- * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
- *																			*
- * Anonymous CVS access to the development source and modification history	*
- * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
- * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
- *     (just hit return, no password is necessary)							*
- * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
- *																			*
  * For Synchronet coding style and modification guidelines, see				*
  * http://www.synchro.net/source.html										*
  *																			*
- * You are encouraged to submit any modifications (preferably in Unix diff	*
- * format) via e-mail to mods@synchro.net									*
- *																			*
  * Note: If this box doesn't appear square, then you need to fix your tabs.	*
  ****************************************************************************/
 
@@ -107,7 +91,7 @@ const char* getHostNameByAddr(const char* str)
 #endif
 	if(str==NULL)
 		return NULL;
-	if((ip=inet_addr(str)) == INADDR_NONE)
+	if((ip=parseIPv4Address(str)) == INADDR_NONE)
 		return str;
 	if((h=gethostbyaddr((char *)&ip,sizeof(ip),AF_INET))==NULL)
 		return NULL;
@@ -125,6 +109,63 @@ void freeNameServerList(str_list_t list)
 	strListFree(&list);
 }
 
+// If the input is invalid, INADDR_NONE (usually -1) is returned
+uint32_t parseIPv4Address(const char* value)
+{
+	uint32_t result = 0;
+
+	if(strchr(value,'.') == NULL)
+		return strtol(value, NULL, 10);
+
+#if defined(__BORLANDC__) || defined(__MINGW32__)
+	result = inet_addr(value); // deprecated function call
+#else
+	if(inet_pton(AF_INET, value, &result) != 1)
+		result = INADDR_NONE;
+#endif
+	return ntohl(result);
+}
+
+struct in6_addr parseIPv6Address(const char* value)
+{
+	struct addrinfo hints = {0};
+	struct addrinfo *res, *cur;
+	struct in6_addr ret = {{{0}}};
+
+	hints.ai_flags = AI_NUMERICHOST|AI_PASSIVE;
+	if(getaddrinfo(value, NULL, &hints, &res))
+		return ret;
+
+	for(cur = res; cur; cur++) {
+		if(cur->ai_addr->sa_family == AF_INET6)
+			break;
+	}
+	if(!cur) {
+		freeaddrinfo(res);
+		return ret;
+	}
+	memcpy(&ret, &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr, sizeof(ret));
+	freeaddrinfo(res);
+	return ret;
+}
+
+const char* IPv4AddressToStr(uint32_t addr, char* dest, size_t size)
+{
+	const char* result;
+	struct in_addr in_addr;
+	in_addr.s_addr = htonl(addr);
+#if defined(__BORLANDC__) || defined(__MINGW32__)
+	result = inet_ntoa(in_addr); // deprecated function call
+	if(result == NULL)
+		return NULL;
+	strncpy(dest, result, size);
+	result = dest;
+#else
+	result = inet_ntop(AF_INET, &in_addr, dest, size);
+#endif
+	return result;
+}
+
 #if NETWRAP_TEST
 int main(int argc, char** argv)
 {
diff --git a/src/xpdev/netwrap.h b/src/xpdev/netwrap.h
index d8fc18f88d..f391ca6541 100644
--- a/src/xpdev/netwrap.h
+++ b/src/xpdev/netwrap.h
@@ -35,6 +35,9 @@ extern "C" {
 DLLEXPORT const char* 	getHostNameByAddr(const char*);
 DLLEXPORT str_list_t	getNameServerList(void);
 DLLEXPORT void			freeNameServerList(str_list_t);
+DLLEXPORT const char*	IPv4AddressToStr(uint32_t, char* dest, size_t size);
+DLLEXPORT uint32_t		parseIPv4Address(const char*);
+DLLEXPORT struct in6_addr parseIPv6Address(const char*);
 
 #if defined(__cplusplus)
 }
-- 
GitLab