From 3e2c907d3b3a9c9ac8cbb64787b6a779742a4a98 Mon Sep 17 00:00:00 2001 From: "Jean-Marc Pigeon (Delson)" Date: Thu, 11 Jul 2024 21:09:12 -0400 Subject: [PATCH] Improving unisoc module --- lib/modrec.c | 12 ++-- lib/subrou.c | 139 ++++++++++++++++++++++++++------------- lib/subrou.h | 13 ++++ lib/unisoc.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++-- lib/unisoc.h | 24 ++++++- 5 files changed, 309 insertions(+), 58 deletions(-) diff --git a/lib/modrec.c b/lib/modrec.c index 243d0a9..7a23be0 100644 --- a/lib/modrec.c +++ b/lib/modrec.c @@ -26,13 +26,12 @@ static _Bool modopen; //boolean module open/close PUBLIC void rec_handlesmtp() { -BINTYP binding; +SOCTYP **bindings; int phase; _Bool proceed; -(void) memset(&binding,'\000',sizeof(BINTYP)); -binding.ip=strdup("127.0.0.25"); -binding.port=strdup("2525"); +bindings=(SOCTYP **)0; +bindings=soc_mkbindinf(bindings,pro_smtp,"127.0.0.25","2525",10); phase=0; proceed=true; while (proceed==true) { @@ -40,8 +39,8 @@ while (proceed==true) { case 0 : //looping forever email receiving processes (void) prc_settitle("emlrec with pid='%06d'",getpid()); break; - case 1 : //Opening a channel - if (soc_setbind(&binding)<0) + case 1 : //Opening ONE channel + if (soc_setbind(*bindings)<0) phase=999; //doc not open! break; case 2 : //Terminating all remaining process @@ -55,6 +54,7 @@ while (proceed==true) { } phase++; } +bindings=soc_freebindinf(bindings); } /* ^L diff --git a/lib/subrou.c b/lib/subrou.c index c3b48e8..7c4a87b 100644 --- a/lib/subrou.c +++ b/lib/subrou.c @@ -62,12 +62,98 @@ return strdup(dropzone); /* name. */ /* */ /********************************************************/ -const char *rou_getversion() +PUBLIC const char *rou_getversion() { return VERSION"."RELEASE; } /* + +*/ +/********************************************************/ +/* */ +/* Procedure to free memory used by a */ +/* string, do not proceed if pointer is NULL. */ +/* */ +/********************************************************/ +char *rou_freestr(register char *str) + +{ +if (str!=(char *)0) { + (void) free(str); + str=(char *)0; + } +return str; +} +/* + +*/ +/********************************************************/ +/* */ +/* Subroutine to get add a pointer (not null) */ +/* to a list of pointer. */ +/* */ +/********************************************************/ +PUBLIC void **rou_addlist(void **list,void *entry) + +{ +if (entry!=(void *)0) { + register int num; + + num=0; + if (list==(void **)0) + list=(void **)calloc(num+2,sizeof(void *)); + else { + while (list[num]!=(void *)0) + num++; + list=realloc((void *)list,(num+2)*sizeof(void *)); + } + list[num]=entry; + num++; + list[num]=(void *)0; + } +return list; +} +/* + +*/ +/********************************************************/ +/* */ +/* Procedure to free one entry part of list */ +/* return true if found, false otherwize. */ +/* */ +/********************************************************/ +PUBLIC _Bool rou_rmlist(void **list,void *entry,freehandler_t handler) + +{ +_Bool found; + +found=false; +if ((list!=(void **)0)&&(entry!=(void **)0)) { + void **ptr; + + ptr=list; + while (*ptr!=(void *)0) { + if (*ptr==entry) { + void **nxt; + + nxt=ptr+1; + if (handler!=(freehandler_t)0) + (void) handler(*ptr); + while (*ptr!=(void *)0) { + *ptr=*nxt; + ptr++; + nxt++; + } + found=true; + break; + } + ptr++; + } + } +return found; +} +/* ^L */ /********************************************************/ @@ -76,7 +162,7 @@ return VERSION"."RELEASE; /* logs. */ /* */ /********************************************************/ -char *rou_setappname(const char *newname) +PUBLIC char *rou_setappname(const char *newname) { char *name; @@ -99,7 +185,7 @@ return name; /* directory if needed */ /* */ /********************************************************/ -char *rou_apppath(const char *path) +PUBLIC char *rou_apppath(const char *path) { char *root; @@ -124,7 +210,7 @@ return newpath; /* Subroutine to log event on syslog */ /* */ /********************************************************/ -void rou_valert(const int dlevel,const char *fmt,va_list ap) +PUBLIC void rou_valert(const int dlevel,const char *fmt,va_list ap) #define DEBMAX 120 @@ -160,7 +246,7 @@ if (debug>=dlevel) /* Subroutine to log event on syslog */ /* */ /********************************************************/ -void rou_alert(const int dlevel,const char *fmt,...) +PUBLIC void rou_alert(const int dlevel,const char *fmt,...) { va_list args; @@ -170,41 +256,6 @@ va_start(args,fmt); va_end(args); } /* -^L -*/ -/********************************************************/ -/* */ -/* Procedure to "open" usager to module. */ -/* homework purpose */ -/* return zero if everything right */ -/* */ -/********************************************************/ -int rou_opensubrou() - -{ -int status; - -status=0; -if (modopen==false) { - debug=0; - foreground=false; - off64_time=(time_t)0; - off_date=(time_t)0; - if (appname!=(char *)0) - (void) free(appname); - appname=strdup(APPNAME); - if (rootdir!=(char *)0) { - (void) free(rootdir); - status=-1; //Rootdir should be found as NULL - } - rootdir=strdup(""); - (void) openlog(APPNAME,LOG_PID,LOG_DAEMON); - (void) rou_alert(0,"Starting: %s-%s",APPNAME,rou_getversion()); - modopen=true; - } -return status; -} -/* */ /********************************************************/ @@ -212,7 +263,7 @@ return status; /* Subroutine to CORE-DUMP the application */ /* */ /********************************************************/ -void rou_crash(const char *fmt,...) +PUBLIC void rou_crash(const char *fmt,...) { #define RELAX 5 @@ -238,7 +289,7 @@ va_end(args); /* message and terminate application */ /* */ /********************************************************/ -void rou_core_dump(const char *fmt,...) +PUBLIC void rou_core_dump(const char *fmt,...) { #define MAXCRASH 10 //maximun crash file within drop zone @@ -321,7 +372,7 @@ if (doabort==true) /* return zero if everything right */ /* */ /********************************************************/ -int rou_modesubrou(_Bool mode) +PUBLIC int rou_modesubrou(_Bool mode) { #define OPEP "subrou.c:rou_modesubrou" @@ -332,6 +383,8 @@ status=0; if (mode!=modopen) { switch ((int)mode) { case true : + off64_time=(time_t)0; + off_date=(time_t)0; (void) srand(getpid()*355); if (foreground==true) (void) srand((int)(M_PI*100000000)); diff --git a/lib/subrou.h b/lib/subrou.h index 06038f1..49be274 100644 --- a/lib/subrou.h +++ b/lib/subrou.h @@ -14,6 +14,8 @@ #define APPNAME "maild" //application name +typedef void (*freehandler_t)(void *); + //--- Variables defined within subrou.c --------- extern int debug; //application debug mode extern _Bool foreground; //process is in foreground mode @@ -26,6 +28,17 @@ extern char *appname; //application "official" name //return program version extern const char *rou_getversion(); +//Procedure to free a string pointer and return +//a NULL pointer +extern char *rou_freestr(char *str); + +//to add a not null pointer to a list of pointer +extern void **rou_addlist(void **list,void *entry); + +//Procedure to free one entry part of list +// return true if found, false otherwize. +extern _Bool rou_rmlist(void **list,void *entry,freehandler_t handler); + //change the application name extern char *rou_setappname(const char *newname); diff --git a/lib/unisoc.c b/lib/unisoc.c index 0a1e82e..dcfdc00 100644 --- a/lib/unisoc.c +++ b/lib/unisoc.c @@ -7,9 +7,13 @@ /********************************************************/ #include #include +#include +#include #include #include +#include #include +#include #include "subrou.h" #include "unisoc.h" @@ -24,18 +28,179 @@ static _Bool modopen; //module open/close status /* -^L + +*/ +/********************************************************/ +/* */ +/* Procedure to free memory used by a */ +/* binding info. */ +/* */ +/* */ +/********************************************************/ +static SOCTYP *freebinding(SOCTYP *binding) + +{ +if (binding!=(SOCTYP *)0) { + binding->port=rou_freestr(binding->port); + binding->ip=rou_freestr(binding->ip); + (void) free(binding); + binding=(SOCTYP *)0; + } +return binding; +} +/* + +*/ +/********************************************************/ +/* */ +/* Procedure to bind a socket to a specific */ +/* address and return the linked handle */ +/* */ +/********************************************************/ +static int bindhandle(struct addrinfo *ai,SOCTYP *binding) + +{ +#define OPEP "unisoc.c:bindhandle," +#define BFSZ 30 //working buffer size + +int handle; +struct linger slg; +char *buf; +int flags; +int phase; +_Bool proceed; + +handle=-1; +(void) memset(&slg,'\000',sizeof(struct linger)); +buf=calloc(BFSZ,sizeof(char)); +flags=0; +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 0 : //lets get a socket + if ((handle=socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol))<0) { + (void) rou_alert(0,"%s Unable to open socket for <%s> (error='%s')", + OPEP,ai->ai_canonname,strerror(errno)); + phase=999; //trouble trouble + } + break; + case 1 : //setting socket option (address) + if (setsockopt(handle,SOL_SOCKET,SO_REUSEADDR,buf,BFSZ*sizeof(char))<0) { + (void) rou_alert(0,"%s Unable to get socket option " + "SO_REUSEADDR for <%s> (error='%s')", + OPEP,ai->ai_canonname,strerror(errno)); + phase=999; //trouble cleanup phase + } + break; + case 2 : //setting socket option (port) + if (setsockopt(handle,SOL_SOCKET,SO_REUSEPORT,buf,BFSZ*sizeof(char))<0) { + (void) rou_alert(0,"%s Unable to get socket option " + "SO_REUSEPORT for <%s> (error='%s')", + OPEP,ai->ai_canonname,strerror(errno)); + phase=999; //trouble cleanup phase + } + break; + case 3 : //SO_LINGER allow Connection reset by peer" + if (setsockopt(handle,SOL_SOCKET,SO_LINGER,&slg,sizeof(slg))<0) { + (void) rou_alert(0,"%s Unable to set socket option " + "SO_LINGER for <%s> (error='%s')", + OPEP,ai->ai_canonname,strerror(errno)); + phase=999; //trouble cleanup phase + } + break; + case 4 : /*getting socket option */ + if ((flags=fcntl(handle,F_GETFL,0))<0) { + (void) rou_alert(0,"%s Unable to set socket descriptor " + "for <%s> (error='%s')", + OPEP,ai->ai_canonname,strerror(errno)); + phase=999; //trouble cleanup phase + } + break; + case 5 : //setting the socket working setting + if (fcntl(handle,F_SETFL,flags|O_NONBLOCK|O_ASYNC)<0) { + (void) rou_alert(0,"%s Unable to set socket in none " + "block mode for <%s> (error='%s')", + OPEP,ai->ai_canonname,strerror(errno)); + phase=999; //trouble cleanup phase + } + break; + case 6 : //getting socket option + if (bind(handle,ai->ai_addr,ai->ai_addrlen)<0) { + (void) rou_alert(0,"%s Unable to bind on IP/port <%s/%s> (error='%s')", + OPEP,ai->ai_canonname,binding->port,strerror(errno)); + phase=999; //trouble cleanup phase + } + break; + case 7 : /*preparing listen */ + if (listen(handle,5)<0) { + (void) rou_alert(0,"%s Unable to listen on IP/port <%s/%s> (error='%s')", + OPEP,ai->ai_canonname,binding->port,strerror(errno)); + phase=999; //trouble cleanup phase + } + break; + case 8 : /*reporting listen */ + (void) rou_alert(1,"Now Listening on IP/PORT <%s/%s>", + ai->ai_canonname,binding->port); + proceed=false; //evrything fine no need to go further + break; + default : /*SAFE Guard */ + if (handle>=0) + close(handle); + proceed=false; + break; + } + phase++; + } +(void) free(buf); +return handle; +#undef OPEP +} +/* + */ /********************************************************/ /* */ -/* Procedure to bind a sockt to a specific */ -/* IP/PORT. */ +/* Procedure to free memory used by a bind */ +/* definition. */ +/* */ +/********************************************************/ +PUBLIC SOCTYP **soc_freebindinf(SOCTYP **bindref) + +{ +if (bindref!=(SOCTYP **)0) { + int i; + + for (i=0;bindref[i]!=(SOCTYP *)0;i++) { + bindref[i]=freebinding(bindref[i]); + } + (void) free(bindref); + bindref=(SOCTYP **)0; + } +return bindref; +} +/* + +*/ +/********************************************************/ +/* */ +/* Procedure to set memory used by a bin */ +/* definition. */ /* */ /********************************************************/ -static int bindhandle(struct addrinfo *ai,BINTYP *binding) +PUBLIC SOCTYP **soc_mkbindinf(SOCTYP **bindings,PROTYP proto, + const char *ip,const char *port,int iteration) { -return -1; +SOCTYP *bininf; + +bininf=(SOCTYP *)calloc(1,sizeof(SOCTYP)); +bininf->proto=proto; +bininf->ip=strdup(ip); +bininf->port=strdup(port); +bininf->iteration=iteration; +bindings=(SOCTYP **)rou_addlist((void **)bindings,(void *)bininf); +return bindings; } /* ^L @@ -46,7 +211,7 @@ return -1; /* IP/PORT. */ /* */ /********************************************************/ -PUBLIC int soc_setbind(BINTYP *binding) +PUBLIC int soc_setbind(SOCTYP *binding) { #define OPEP "unisoc.c:soc_setbind" @@ -69,7 +234,7 @@ proceed=true; while (proceed==true) { switch (phase) { case 0 : //sanity check - if (binding==(BINTYP *)0) { + if (binding==(SOCTYP *)0) { (void) rou_alert(0,"%s, socket binding reference is NULL (Bug!?)",OPEP); phase=999; //no need to go further } diff --git a/lib/unisoc.h b/lib/unisoc.h index b02b943..b636517 100644 --- a/lib/unisoc.h +++ b/lib/unisoc.h @@ -11,14 +11,34 @@ #include #include +//defining email protocol value. +typedef enum { + pro_smtp, //text SMTP protocol, in clear mode + pro_startls, //Text SMTP protocol, encrypted upon request + pro_smtps, //Text SMTP protocol, text encrypted from start + pro_unknwn //Protcole undefined + }PROTYP; + typedef struct { + PROTYP proto; //Connexion protocol type char *ip; //Binding IP //IPV4 or IPV6 char *port; //Binding Port time_t lasttry; //successful binding last time - }BINTYP; + int iteration; //number of handle ready on the soc + int handle; //connexion handle + }SOCTYP; + +//procedure to free all memory used by a TCP socket +//definition (once closed) +extern SOCTYP **soc_freebindinf(SOCTYP **bindref); + +//procedure to assign memory to be used by a TCP socket +//definition +extern SOCTYP **soc_mkbindinf(SOCTYP **bindings,PROTYP proto, + const char *ip,const char *port,int iteration); //procedure to open a socketand retunr handle to socket -extern int soc_setbind(BINTYP *binding); +extern int soc_setbind(SOCTYP *binding); //homework to be done before starting/stopping module. extern int soc_modeunisoc(_Bool mode); -- 2.47.3