From 4b3ba1f793bf4cd5c1d93d0042a29aaa816b5a2b Mon Sep 17 00:00:00 2001
From: rswindell <>
Date: Thu, 13 Oct 2005 01:44:53 +0000
Subject: [PATCH] Support per-server/service/protocol socket option settings in
 ctrl/sockopts.ini (replacing sockopts.cfg).

---
 src/sbbs3/execnet.cpp |   4 +-
 src/sbbs3/ftpsrvr.c   |   2 +-
 src/sbbs3/ident.c     |   2 +-
 src/sbbs3/js_socket.c |  14 +++--
 src/sbbs3/mailsrvr.c  |   2 +-
 src/sbbs3/main.cpp    |   8 +--
 src/sbbs3/sbbs.h      |   5 +-
 src/sbbs3/services.c  |   9 +--
 src/sbbs3/sockopts.c  | 126 ++++++++++++++++++++++--------------------
 src/sbbs3/telgate.cpp |   2 +-
 src/sbbs3/websrvr.c   |   2 +-
 src/sbbs3/xtrn.cpp    |   4 +-
 12 files changed, 97 insertions(+), 83 deletions(-)

diff --git a/src/sbbs3/execnet.cpp b/src/sbbs3/execnet.cpp
index 8b6501f757..a9096235d4 100644
--- a/src/sbbs3/execnet.cpp
+++ b/src/sbbs3/execnet.cpp
@@ -61,7 +61,7 @@ int sbbs_t::exec_net(csi_t* csi)
 				return(0);
 			if(lp!=NULL) {
 
-				SOCKET sock=open_socket(SOCK_STREAM);
+				SOCKET sock=open_socket(SOCK_STREAM, NULL);
 				if(sock!=INVALID_SOCKET) {
 
 					SOCKADDR_IN	addr;
@@ -544,7 +544,7 @@ SOCKET sbbs_t::ftp_data_sock(csi_t* csi, SOCKET ctrl_sock, SOCKADDR_IN* addr)
 		return(INVALID_SOCKET);
 	}
 
-	if((data_sock=open_socket(SOCK_STREAM))==INVALID_SOCKET) {
+	if((data_sock=open_socket(SOCK_STREAM, NULL))==INVALID_SOCKET) {
 		csi->socket_error=ERROR_VALUE;
 		return(INVALID_SOCKET);
 	}
diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c
index f4ae3d858e..06bc13fd9c 100644
--- a/src/sbbs3/ftpsrvr.c
+++ b/src/sbbs3/ftpsrvr.c
@@ -231,7 +231,7 @@ static SOCKET ftp_open_socket(int type)
 	if(sock!=INVALID_SOCKET && startup!=NULL && startup->socket_open!=NULL) 
 		startup->socket_open(startup->cbdata,TRUE);
 	if(sock!=INVALID_SOCKET) {
-		if(set_socket_options(&scfg, sock, error))
+		if(set_socket_options(&scfg, sock, "FTP", error, sizeof(error)))
 			lprintf(LOG_ERR,"%04d !ERROR %s",sock, error);
 		sockets++;
 #ifdef _DEBUG
diff --git a/src/sbbs3/ident.c b/src/sbbs3/ident.c
index 1138e15fdb..0739631f35 100644
--- a/src/sbbs3/ident.c
+++ b/src/sbbs3/ident.c
@@ -56,7 +56,7 @@ char* identify(SOCKADDR_IN* client_addr, u_short local_port, char* buf
 		timeout=10;
 
 	do {
-		if((sock = open_socket(SOCK_STREAM)) == INVALID_SOCKET) {
+		if((sock = open_socket(SOCK_STREAM, "ident")) == INVALID_SOCKET) {
 			sprintf(buf,"ERROR %d creating socket",ERROR_VALUE);
 			break;
 		}
diff --git a/src/sbbs3/js_socket.c b/src/sbbs3/js_socket.c
index 7f5078751d..90ec8b731a 100644
--- a/src/sbbs3/js_socket.c
+++ b/src/sbbs3/js_socket.c
@@ -1307,18 +1307,24 @@ static JSBool
 js_socket_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
 	int32	type=SOCK_STREAM;	/* default = TCP */
+	uintN	i;
 	private_t* p;
+	char*	sock_service=NULL;
 
-	if(argc)
-		JS_ValueToInt32(cx,argv[0],&type);
-
+	for(i=0;i<argc;i++) {
+		if(JSVAL_IS_NUMBER(argv[i]))
+			JS_ValueToInt32(cx,argv[i],&type);
+		else if(sock_service==NULL)
+			sock_service=JS_GetStringBytes(JS_ValueToString(cx,argv[i]));
+	}
+		
 	if((p=(private_t*)malloc(sizeof(private_t)))==NULL) {
 		JS_ReportError(cx,"malloc failed");
 		return(JS_FALSE);
 	}
 	memset(p,0,sizeof(private_t));
 
-	if((p->sock=open_socket(type))==INVALID_SOCKET) {
+	if((p->sock=open_socket(type,sock_service))==INVALID_SOCKET) {
 		JS_ReportError(cx,"open_socket failed with error %d",ERROR_VALUE);
 		return(JS_FALSE);
 	}
diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index e28f9b2a79..f74ad15b73 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -205,7 +205,7 @@ SOCKET mail_open_socket(int type)
 	if(sock!=INVALID_SOCKET && startup!=NULL && startup->socket_open!=NULL) 
 		startup->socket_open(startup->cbdata,TRUE);
 	if(sock!=INVALID_SOCKET) {
-		if(set_socket_options(&scfg, sock,error))
+		if(set_socket_options(&scfg, sock, "mail", error, sizeof(error)))
 			lprintf(LOG_ERR,"%04d !ERROR %s",sock,error);
 
 		sockets++;
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index b04f60f2f9..d1402275e9 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -174,7 +174,7 @@ int eprintf(int level, char *fmt, ...)
     return(startup->event_lputs(level,sbuf));
 }
 
-SOCKET open_socket(int type)
+SOCKET open_socket(int type, const char* service)
 {
 	SOCKET	sock;
 	char	error[256];
@@ -182,7 +182,7 @@ SOCKET open_socket(int type)
 	sock=socket(AF_INET, type, IPPROTO_IP);
 	if(sock!=INVALID_SOCKET && startup!=NULL && startup->socket_open!=NULL) 
 		startup->socket_open(startup->cbdata,TRUE);
-	if(sock!=INVALID_SOCKET && set_socket_options(&scfg, sock, error))
+	if(sock!=INVALID_SOCKET && set_socket_options(&scfg, sock, service, error, sizeof(error)))
 		lprintf(LOG_ERR,"%04d !ERROR %s",sock,error);
 
 	return(sock);
@@ -3958,7 +3958,7 @@ void DLLCALL bbs_thread(void* arg)
 
     /* open a socket and wait for a client */
 
-    telnet_socket = open_socket(SOCK_STREAM);
+    telnet_socket = open_socket(SOCK_STREAM, "bbs");
 
 	if(telnet_socket == INVALID_SOCKET) {
 		lprintf(LOG_ERR,"!ERROR %d creating Telnet socket", ERROR_VALUE);
@@ -4002,7 +4002,7 @@ void DLLCALL bbs_thread(void* arg)
 
 		/* open a socket and wait for a client */
 
-		rlogin_socket = open_socket(SOCK_STREAM);
+		rlogin_socket = open_socket(SOCK_STREAM, "bbs");
 
 		if(rlogin_socket == INVALID_SOCKET) {
 			lprintf(LOG_ERR,"!ERROR %d creating RLogin socket", ERROR_VALUE);
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index bfb2889241..2449effd51 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -874,7 +874,8 @@ extern "C" {
 
 	/* sockopt.c */
 	DLLEXPORT int		DLLCALL sockopt(char* str, int* level);
-	DLLEXPORT int		DLLCALL set_socket_options(scfg_t* cfg, SOCKET sock, char* error);
+	DLLEXPORT int		DLLCALL set_socket_options(scfg_t* cfg, SOCKET sock, const char* section
+		,char* error, size_t errlen);
 
 	/* xtrn.cpp */
 	DLLEXPORT char*		DLLCALL cmdstr(scfg_t* cfg, user_t* user, const char* instr
@@ -1046,7 +1047,7 @@ BOOL 	md(char *path);
 	int 	lputs(int level, char *);			/* log output */
 	int 	lprintf(int level, char *fmt, ...);	/* log output */
 	int 	eprintf(int level, char *fmt, ...);	/* event log */
-	SOCKET	open_socket(int type);
+	SOCKET	open_socket(int type, const char* service);
 	SOCKET	accept_socket(SOCKET s, SOCKADDR* addr, socklen_t* addrlen);
 	int		close_socket(SOCKET);
 	u_long	resolve_ip(char *addr);
diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c
index 1f9109c741..802e2cd46a 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -212,7 +212,7 @@ static void thread_down(void)
 		startup->thread_up(startup->cbdata,FALSE,FALSE);
 }
 
-static SOCKET open_socket(int type)
+static SOCKET open_socket(int type, const char* service)
 {
 	char	error[256];
 	SOCKET	sock;
@@ -222,7 +222,7 @@ static SOCKET open_socket(int type)
 		startup->socket_open(startup->cbdata,TRUE);
 	if(sock!=INVALID_SOCKET) {
 		sockets++;
-		if(set_socket_options(&scfg, sock, error))
+		if(set_socket_options(&scfg, sock, service, error, sizeof(error)))
 			lprintf(LOG_ERR,"%04d !ERROR %s",sock, error);
 
 #if 0 /*def _DEBUG */
@@ -1696,7 +1696,8 @@ void DLLCALL services_thread(void* arg)
 			service[i].socket=INVALID_SOCKET;
 
 			if((socket = open_socket(
-				(service[i].options&SERVICE_OPT_UDP) ? SOCK_DGRAM : SOCK_STREAM))
+				(service[i].options&SERVICE_OPT_UDP) ? SOCK_DGRAM : SOCK_STREAM
+				,service[i].protocol))
 				==INVALID_SOCKET) {
 				lprintf(LOG_ERR,"!ERROR %d opening %s socket"
 					,ERROR_VALUE, service[i].protocol);
@@ -1892,7 +1893,7 @@ void DLLCALL services_thread(void* arg)
 						continue;
 					}
 
-					if((client_socket = open_socket(SOCK_DGRAM))
+					if((client_socket = open_socket(SOCK_DGRAM, service[i].protocol))
 						==INVALID_SOCKET) {
 						FREE_AND_NULL(udp_buf);
 						lprintf(LOG_ERR,"%04d %s !ERROR %d opening socket"
diff --git a/src/sbbs3/sockopts.c b/src/sbbs3/sockopts.c
index fe30e3a893..be79d44312 100644
--- a/src/sbbs3/sockopts.c
+++ b/src/sbbs3/sockopts.c
@@ -1,6 +1,6 @@
 /* sockopts.c */
 
-/* Set socket options based on contents of ctrl/sockopts.cfg */
+/* Set socket options based on contents of ctrl/sockopts.ini */
 
 /* $Id$ */
 
@@ -8,7 +8,7 @@
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
  *																			*
- * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html		*
  *																			*
  * This program is free software; you can redistribute it and/or			*
  * modify it under the terms of the GNU General Public License				*
@@ -36,14 +36,13 @@
  ****************************************************************************/
 
 #include "sbbs.h"
+#include "ini_file.h"	/* ini file API */
 
-typedef struct {
+static struct {
 	char*	name;
 	int		level;
 	int		value;
-} sockopt_name;
-
-static const sockopt_name option_names[] = {
+} option_names[] = {
 	{ "TYPE",				SOL_SOCKET,		SO_TYPE				},
 	{ "DEBUG",				SOL_SOCKET,		SO_DEBUG			},
 	{ "LINGER",				SOL_SOCKET,		SO_LINGER			},
@@ -104,6 +103,7 @@ static const sockopt_name option_names[] = {
 	{ NULL }
 };
 
+/* This function is used by js_socket.c -> js_get/setsockopt() */
 int DLLCALL sockopt(char* str, int* level)
 {
 	int i;
@@ -120,60 +120,39 @@ int DLLCALL sockopt(char* str, int* level)
 	return(strtoul(str,NULL,0));
 }
 
-int DLLCALL set_socket_options(scfg_t* cfg, SOCKET sock, char* error)
+static int parse_sockopts_section(str_list_t list, SOCKET sock, int type, const char* section
+						 ,char* error, size_t errlen)
 {
-	char		cfgfile[MAX_PATH+1];
-	char		str[256];
-	char*		p;
+	int			i;
+	int			result;
 	char*		name;
 	BYTE*		vp;
-	FILE*		fp;
+	socklen_t	len;
 	int			option;
 	int			level;
 	int			value;
-	int			type;
-	int			result=0;
 	LINGER		linger;
-	socklen_t	len;
 
-	/* Set user defined socket options */
-	sprintf(cfgfile,"%ssockopts.cfg",cfg->ctrl_dir);
-	if((fp=fopen(cfgfile,"r"))==NULL)
-		return(0);
-
-	len = sizeof(type);
-	result=getsockopt(sock,SOL_SOCKET,SO_TYPE,(void*)&type,&len);
-	if(result) {
-		sprintf(error,"%d getting socket option (TYPE, %d)"
-			,ERROR_VALUE, SO_TYPE);
-		return(result);
-	}
-
-	while(!feof(fp)) {
-		if(!fgets(str,sizeof(str),fp))
-			break;
-		name=str;
-		while(*name && *name<=' ') name++;
-		if(*name==';' || *name==0)	/* blank line or comment */
+	for(i=0;option_names[i].name!=NULL;i++) {
+		name = option_names[i].name;
+		if(!iniValueExists(list,section,name))
 			continue;
-		p=name;
-		while(*p && *p>' ') p++;
-		if(*p) *(p++)=0;
-		if((option=sockopt(name,&level))==-1)
-			continue;
-		if(level==IPPROTO_TCP && type!=SOCK_STREAM)
-			continue;
-		while(*p && *p<=' ') p++;
-		len=sizeof(value);
-		value=strtol(p,NULL,0);
+		value=iniGetInteger(list, section, name, 0);
+
 		vp=(BYTE*)&value;
-		while(*p && *p>' ') p++;
-		if(*p) p++;
-		while(*p && *p<=' ') p++;
+		len=sizeof(value);
+
+		level	= option_names[i].level;
+		option	= option_names[i].value;
+
 		switch(option) {
 			case SO_LINGER:
-				linger.l_onoff = value;
-				linger.l_linger = (int)strtol(p,NULL,0);
+				if(value) {
+					linger.l_onoff = TRUE;
+					linger.l_linger = value;
+				} else {
+					ZERO_VAR(linger);
+				}
 				vp=(BYTE*)&linger;
 				len=sizeof(linger);
 				break;
@@ -182,21 +161,48 @@ int DLLCALL set_socket_options(scfg_t* cfg, SOCKET sock, char* error)
 					continue;
 				break;
 		}
-#if 0
-		lprintf("%04d setting socket option: %s to %d", sock, str, value);
-#endif
-		result=setsockopt(sock,level,option,vp,len);
-		if(result) {
-			sprintf(error,"%d setting socket option (%s, %d) to %d"
+
+		if((result=setsockopt(sock,level,option,vp,len)) != 0) {
+			safe_snprintf(error,errlen,"%d setting socket option (%s, %d) to %d"
 				,ERROR_VALUE, name, option, value);
-			break;
+			return(result);
 		}
-#if 0
-		len = sizeof(value);
-		getsockopt(sock,level,option,(void*)&value,&len);
-		lprintf("%04d socket option: %s set to %d", sock, name, value);
-#endif
 	}
+
+	return(0);
+}
+
+
+int DLLCALL set_socket_options(scfg_t* cfg, SOCKET sock, const char* section, char* error, size_t errlen)
+{
+	char		cfgfile[MAX_PATH+1];
+	FILE*		fp;
+	int			type;
+	int			result=0;
+	str_list_t	list;
+	socklen_t	len;
+
+	/* Set user defined socket options */
+	iniFileName(cfgfile,sizeof(cfgfile),cfg->ctrl_dir,"sockopts.ini");
+	if((fp=iniOpenFile(cfgfile,FALSE))==NULL)
+		return(0);
+	list=iniReadFile(fp);
 	fclose(fp);
+
+	len = sizeof(type);
+	result=getsockopt(sock,SOL_SOCKET,SO_TYPE,(void*)&type,&len);
+	if(result) {
+		sprintf(error,"%d getting socket option (TYPE, %d)"
+			,ERROR_VALUE, SO_TYPE);
+		return(result);
+	}
+
+	result=parse_sockopts_section(list,sock,type,ROOT_SECTION,error,errlen);
+
+	if(result==0 && section!=NULL)
+		result=parse_sockopts_section(list,sock,type,section,error,errlen);
+
+	iniFreeStringList(list);
+
 	return(result);
 }
diff --git a/src/sbbs3/telgate.cpp b/src/sbbs3/telgate.cpp
index b98a26a25b..02af027cce 100644
--- a/src/sbbs3/telgate.cpp
+++ b/src/sbbs3/telgate.cpp
@@ -71,7 +71,7 @@ void sbbs_t::telnet_gate(char* destaddr, ulong mode)
 		return;
 	}
 
-    if((remote_socket = open_socket(SOCK_STREAM)) == INVALID_SOCKET) {
+    if((remote_socket = open_socket(SOCK_STREAM, "bbs")) == INVALID_SOCKET) {
 		errormsg(WHERE,ERR_OPEN,"socket",0);
 		return;
 	}
diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c
index 0dc0e03966..49c2b1c0cd 100644
--- a/src/sbbs3/websrvr.c
+++ b/src/sbbs3/websrvr.c
@@ -698,7 +698,7 @@ static SOCKET open_socket(int type)
 	if(sock!=INVALID_SOCKET && startup!=NULL && startup->socket_open!=NULL) 
 		startup->socket_open(startup->cbdata,TRUE);
 	if(sock!=INVALID_SOCKET) {
-		if(set_socket_options(&scfg, sock,error))
+		if(set_socket_options(&scfg, sock, "web", error, sizeof(error)))
 			lprintf(LOG_ERR,"%04d !ERROR %s",sock,error);
 
 		sockets++;
diff --git a/src/sbbs3/xtrn.cpp b/src/sbbs3/xtrn.cpp
index c8dce4ce2f..fb9c2d66df 100644
--- a/src/sbbs3/xtrn.cpp
+++ b/src/sbbs3/xtrn.cpp
@@ -1039,7 +1039,7 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
 			ioctlsocket(client_socket, FIONBIO, &l);
 
 			/* Re-set socket options */
-			if(set_socket_options(&cfg, client_socket, str))
+			if(set_socket_options(&cfg, client_socket, "bbs", str, sizeof(str)))
 				lprintf(LOG_ERR,"%04d !ERROR %s",client_socket, str);
 
 			if(input_thread_mutex_locked && input_thread_running) {
@@ -1928,7 +1928,7 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
 		ioctlsocket(client_socket, FIONBIO, &l);
 
 		/* Re-set socket options */
-		if(set_socket_options(&cfg, client_socket, str))
+		if(set_socket_options(&cfg, client_socket, "bbs", str, sizeof(str)))
 			lprintf(LOG_ERR,"%04d !ERROR %s",client_socket, str);
 
 		curatr=~0;			// Can't guarantee current attributes
-- 
GitLab