From 5a8010805100d90017ea384dcc58aad06f3064d4 Mon Sep 17 00:00:00 2001 From: "Jean-Marc Pigeon (Delson)" Date: Mon, 5 Aug 2024 18:45:22 -0400 Subject: [PATCH] Mejor reorganisation about devsoc module --- Makefile | 1 - app/Makefile | 1 + lib/Makefile | 2 + lib/devsoc.c | 517 ++++++++++++++++++++++++++++++++++++++++++++++----- lib/devsoc.h | 22 ++- lib/gestcp.c | 233 ++--------------------- lib/gestcp.h | 9 +- lib/modrec.c | 11 +- lib/subrou.c | 2 +- lib/unissl.c | 91 ++++++++- lib/unissl.h | 9 + 11 files changed, 612 insertions(+), 286 deletions(-) diff --git a/Makefile b/Makefile index b191f22..3919fb5 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,6 @@ install : #-------------------------------------------------------------------- SUBDIR = \ - kleenex \ lib \ app \ diff --git a/app/Makefile b/app/Makefile index 1996e6d..1246d9b 100644 --- a/app/Makefile +++ b/app/Makefile @@ -37,6 +37,7 @@ CFLAGS = -I ../lib -Wall $(OPTIME) LIBAI = ../lib/libAI.a LIBS = $(LIBAI) \ -lcrypto \ + -lssl \ #-------------------------------------------------------------------- #Dependances diff --git a/lib/Makefile b/lib/Makefile index a7e2650..86644be 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -44,7 +44,9 @@ gestcp.o: \ devsoc.o: \ subrou.h \ + unieml.h \ uniprc.h \ + unissl.h \ devsoc.h devsoc.c unieml.o: \ diff --git a/lib/devsoc.c b/lib/devsoc.c index aefaf7c..a9007f0 100644 --- a/lib/devsoc.c +++ b/lib/devsoc.c @@ -10,12 +10,14 @@ #include #include #include +#include #include #include #include #include #include "subrou.h" +#include "unieml.h" #include "uniprc.h" #include "unissl.h" #include "devsoc.h" @@ -27,14 +29,21 @@ #define HINTFLG AI_CANONNAME #endif +#define MXCARIN 200 //maximun number of char within carpile + typedef struct { PROTYP proto; //Connexion protocol type + int handle; //connexion handle + SSL_CTX *ctx; //encryption context + int maxcarin; //absolute number within carin + char *EOL; //End of line marker + int carin; //number of char within incpt; + char *carpile; //area to store incoming char char *ip; //Binding IP //IPV4 or IPV6 char *port; //Binding Port char *hostname; //binding hostname time_t lasttry; //successful binding last time int iteration; //number of soc slot used on the IP - int handle; //connexion handle }SOCTYP; static _Bool modopen; //module open/close status @@ -48,7 +57,7 @@ static _Bool modopen; //module open/close status /* */ /* */ /********************************************************/ -static SOCPTR *freebinding(SOCPTR *socptr) +static SOCPTR *freesocket(SOCPTR *socptr) { if (socptr!=(SOCPTR *)0) { @@ -58,6 +67,7 @@ if (socptr!=(SOCPTR *)0) { soc->hostname=rou_freestr(soc->hostname); soc->ip=rou_freestr(soc->ip); soc->port=rou_freestr(soc->port); + soc->carpile=rou_freestr(soc->carpile); (void) free(soc); socptr=(SOCPTR *)0; } @@ -68,6 +78,92 @@ return socptr; */ /********************************************************/ /* */ +/* Procedure to create a new socket */ +/* */ +/* */ +/********************************************************/ +static SOCTYP *newsocket() + +{ +SOCTYP *soc; + +soc=(SOCTYP *)calloc(1,sizeof(SOCTYP)); +soc->maxcarin=MXCARIN; +soc->carin=0; +soc->EOL=strdup(CRLF); +soc->carpile=(char *)calloc(soc->maxcarin,sizeof(char)); +return soc; +} +/* + +*/ +/********************************************************/ +/* */ +/* Procedure to duplicate a socket */ +/* */ +/********************************************************/ +static SOCTYP *dupsocket(SOCTYP *soc) + +{ +SOCTYP *newsoc; + +newsoc=(SOCTYP *)newsocket(); +newsoc->proto=soc->proto; +newsoc->hostname=strdup(soc->hostname); +newsoc->ip=strdup(soc->ip); +newsoc->port=strdup(soc->port); +newsoc->iteration=soc->iteration; +newsoc->handle=-1; +return newsoc; +} +/* + +*/ +/********************************************************/ +/* */ +/* Procedure to wait and get a new handle */ +/* */ +/********************************************************/ +static int getnewhandle(SOCTYP *soc) + +{ +#define OPEP "devsoc.c:getnewhandle" + +int newhandle; + +if ((newhandle=accept(soc->handle,(SOCKADDR *)0,(socklen_t *)0))<0) { + if (errno==EAGAIN) + errno=EWOULDBLOCK; + switch (errno) { + case EWOULDBLOCK : + (void) rou_alert(0,"%s Socket on IP/PORT <%s/%s> is in no_block mode " + "(Bug?!, errno=<%s>)", + OPEP,soc->ip,soc->port,strerror(errno)); + break; + case EINVAL : + (void) rou_alert(0,"%s Socket on IP/PORT <%s/%s> not available " + "(Bug?!, errno=<%s>)", + OPEP,soc->ip,soc->port,strerror(errno)); + break; + case EINTR : + (void) rou_alert(3,"%s Socket on IP/PORT <%s/%s> got a signal " + "(errno=<%s>)", + OPEP,soc->ip,soc->port,strerror(errno)); + break; + default : + (void) rou_alert(0,"%s Unexpected error on IP/PORT <%s/%s> (errno=<%s>)", + OPEP,soc->ip,soc->port,strerror(errno)); + break; + } + } +return newhandle; +#undef OPEP +} +/* + +*/ +/********************************************************/ +/* */ /* Procedure to bind a socket to a specific */ /* address and return the linked handle */ /* */ @@ -75,7 +171,7 @@ return socptr; static int bindhandle(struct addrinfo *ai,SOCTYP *soc) { -#define OPEP "unisoc.c:bindhandle," +#define OPEP "devsoc.c:bindhandle," #define BFSZ 30 //working buffer size int handle; @@ -167,7 +263,7 @@ if (socptr!=(SOCPTR **)0) { socs=(SOCTYP **)socptr; for (i=0;socs[i]!=(SOCTYP *)0;i++) { - socs[i]=freebinding(socs[i]); + socs[i]=freesocket(socs[i]); } (void) free(socs); socptr=(SOCPTR **)0; @@ -189,7 +285,7 @@ PUBLIC SOCPTR **soc_mkbindinf(SOCPTR **socptr,PROTYP proto, { SOCTYP *soc; -soc=(SOCTYP *)calloc(1,sizeof(SOCTYP)); +soc=newsocket(); soc->proto=proto; soc->ip=strdup(ip); soc->port=strdup(port); @@ -229,7 +325,7 @@ return iterations; PUBLIC _Bool soc_openbinding(SOCPTR *socptr) { -#define OPEP "unisoc.c:soc_openbinding" +#define OPEP "devsoc.c:soc_openbinding" _Bool done; SOCTYP *soc; @@ -322,7 +418,7 @@ return done; PUBLIC void soc_closebinding(SOCPTR *socptr) { -#define OPEP "unisoc.c:soc_closebinding" +#define OPEP "devsoc.c:soc_closebinding" SOCTYP *soc; int phase; @@ -363,63 +459,390 @@ while (proceed==true) { */ /********************************************************/ /* */ +/* Procedure to wait for incoming character on */ +/* socket, waiting up to attend second. */ +/* */ +/********************************************************/ +PUBLIC int soc_waitforchar(SOCPTR *socptr,TIMESPEC *attend) + +{ +register int status; + +status=-1; +if (socptr!=(SOCTYP *)0) { + struct pollfd polling[1]; + + polling[0].events=POLLIN|POLLPRI; + polling[0].revents=(short)0; + polling[0].fd=((SOCTYP *)socptr)->handle; + status=ppoll(polling,1,attend,(sigset_t *)0); + } +return status; +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to return the next available line */ +/* within the socket carpile. */ +/* */ +/********************************************************/ +PUBLIC int soc_getnextline(SOCPTR *socptr,char **lineptr) + +{ +#define OPEP "devsoc.c:soc_getnextline" + +int got; +register SOCTYP *soc; +char *eol; +int phase; +_Bool proceed; + +*lineptr=(char *)0; +got=0; +eol=(char *)0; +soc=(SOCTYP *)socptr; +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 0 : //Do we have dat in carpile + if (soc==(SOCTYP *)0) { + (void) rou_alert(0,"%s, socket binding reference is NULL (Bug!?)",OPEP); + phase=999; //no need to go further + } + case 1 : //Do we have char available in carpile + if (soc->carin==0) + phase=999; //No char,no need to check for line + break; + case 2 : //Do we have a CRLF + eol=strstr(soc->carpile,soc->EOL); + if (eol==(char *)0) + phase=999; //No End Of Line yet + break; + case 3 : //duplicating carpile + *lineptr=calloc(soc->carin+1,sizeof(char)); + *eol='\000'; + (void) strcpy(*lineptr,soc->carpile); + (void) strcat(*lineptr,soc->EOL); + got=strlen(*lineptr); + break; + case 4 : //managing carpile + soc->carin-=strlen(*lineptr); + if (soc->carin>0) + (void) memmove(soc->carpile,soc->carpile+strlen(*lineptr),soc->carin); + soc->carpile[soc->carin]='\000'; + break; + default : //SAFE guard + proceed=false; + break; + } + phase++; + } +return got; +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to send data to a tcp socket. */ +/* return the number of character transmitted, is */ +/* unable to send char return -1; */ +/* */ +/********************************************************/ +PUBLIC int soc_writebuffer(SOCPTR *socptr,char *buffer,int tosend) + +{ +#define OPEP "devsoc.c:soc_writebuffer" + +int sent; +SOCTYP *soc; + +sent=-1; +soc=(SOCTYP *)socptr; +if (soc!=(SOCTYP *)0) { + int got; + + got=recv(soc->handle,(char *)0,0,MSG_PEEK); + switch (got) { + case -1 : + if (errno==EWOULDBLOCK) + errno=EAGAIN; + switch (errno) { + case EAGAIN : + sent=send(soc->handle,buffer,tosend,0); + break; + default : + (void) rou_alert(9,"%s, Unexpected status '%02d' error=<%s> (errno='%d')\n", + OPEP,got,strerror(errno),errno); + break; + } + default : + (void) fprintf(stderr,"Got JMPDBG'%02d'\n",got); + break; + } + } +return sent; +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to read incoming character from the */ +/* socket. */ +/* */ +/********************************************************/ +PUBLIC void soc_receive(SOCPTR *socptr) + +{ +SOCTYP *soc; + +soc=(SOCTYP *)socptr; +if (soc!=(SOCTYP *)0) { + int got; + int limit; + + limit=(soc->maxcarin-soc->carin)-1; + got=recv(soc->handle,soc->carpile+soc->carin,limit,MSG_DONTWAIT); + switch (got) { + case -1 : //do not block + if (errno==EWOULDBLOCK) + errno=EAGAIN; + switch (errno) { + case EAGAIN : //no char available + break; + default : + (void) fprintf(stderr,"JMPDBG soc_receive error=<%s>\n",strerror(errno)); + break; + } + break; + case 0 : //EOL? + break; + default : //we got som char from remote + soc->carin+=got; //managing carpile + soc->carpile[soc->carin]='\000'; + break; + } + } +} +/* +^L +*/ +/********************************************************/ +/* */ /* Procedure to wait an accept a connexion comming */ /* from a remote client. */ /* return the handle */ /* */ /********************************************************/ -PUBLIC int soc_accept(SOCPTR *socptr,int pos) +PUBLIC SOCPTR *soc_accept(SOCPTR *socptr,int pos) { -#define OPEP "unisoc.c:soc_accept" +#define OPEP "devsoc.c:soc_accept" +SOCTYP *newsoc; int newhandle; -register SOCTYP *soc; +SOCTYP *soc; +int flags; +int phase; +_Bool proceed; +newsoc=(SOCTYP *)0; newhandle=-1; soc=(SOCTYP *)socptr; +flags=0; +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 0 : //checking if soc is available + if (soc==(SOCTYP *)0) { + (void) rou_core_dump("%s, socket descripteur missing (Bug?)",OPEP); + phase=999; //never reached + } + break; + case 1 : //display ready on process status; + (void) prc_settitle("%s waiting on [%s:%s] (%02d/%02d)", + appname,soc->ip,soc->port,pos,soc->iteration); + break; + case 2 : //getting the new handle + if ((newhandle=getnewhandle(soc))<0) { + newhandle=-1; + phase=999; //no need to go further + } + break; + case 3 : //getting newhandle flag + if ((flags=fcntl(newhandle,F_GETFL,0))<0) { + (void) rou_core_dump("%s, Unable to get socket descripteur on " + "IP/PORT <%s/%s> (Bug? error=<%s>)", + OPEP,soc->ip,soc->port,strerror(errno)); + phase=999; //never reached + } + break; + case 4 : //setting newhandle working mode + if ((flags=fcntl(newhandle,F_SETFL,flags|O_NONBLOCK|O_ASYNC))<0) { + (void) rou_core_dump("%s, Unable to set socket descripteur on " + "IP/PORT <%s/%s> (Bug? error=<%s>)", + OPEP,soc->ip,soc->port,strerror(errno)); + phase=999; //never reached + } + break; + case 5 : //preparing a new socket + newsoc=dupsocket(soc); + newsoc->handle=newhandle; + break; + case 6 : //configuring extra socket features + switch (newsoc->proto) { + case pro_smtp : //plain socket + case pro_starttls : //plain socket + STARTTLS + phase=999; + break; + case pro_smtps : //set secure socket + newsoc->ctx=ssl_getctx(true); //ssl in server mode + break; + default : //undefined socket type??? + (void) rou_alert(0,"%s, Undefined socket protocol='%d' (Bug?)", + OPEP,soc->proto); + break; + } + break; + default : //SAFE guard + proceed=false; + break; + } + phase++; + } +return (SOCPTR *)newsoc; +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to return the addrename or port */ +/* for local or remote socket. */ +/* */ +/********************************************************/ +PUBLIC char *soc_getaddrinfo(SOCPTR *socptr,_Bool local,_Bool ip) + +{ +#define OPEP "devsoc.c:soc_getaddrinfo" + +char *data; +SOCTYP *soc; +int mode; + +data=(char *)0; +soc=(SOCTYP *)socptr; +mode=NI_NAMEREQD; +if (local==false) + mode=NI_NUMERICHOST; +mode|=NI_NUMERICSERV; if (soc!=(SOCTYP *)0) { - (void) prc_settitle("Waiting contact (%02d/%02d) on %s:%s", - pos,soc->iteration,soc->ip,soc->port); - if ((newhandle=accept(soc->handle,(SOCKADDR *)0,(socklen_t *)0))<0) { - if (errno==EAGAIN) - errno=EWOULDBLOCK; - switch (errno) { - case EWOULDBLOCK : - (void) rou_alert(0,"%s Socket on IP/PORT <%s/%s> is in no_block mode " - "(Bug?!, errno=<%s>)", - OPEP,soc->ip,soc->port,strerror(errno)); - break; - case EINVAL : - (void) rou_alert(0,"%s Socket on IP/PORT <%s/%s> not available " - "(Bug?!, errno=<%s>)", - OPEP,soc->ip,soc->port,strerror(errno)); - break; - case EINTR : - (void) rou_alert(0,"%s Socket on IP/PORT <%s/%s> got a signal " - "(errno=<%s>)", - OPEP,soc->ip,soc->port,strerror(errno)); - break; - default : - (void) rou_alert(0,"%s Unexpected error on IP/PORT <%s/%s> (errno=<%s>)", - OPEP,soc->ip,soc->port,strerror(errno)); - break; - } + int status; + struct sockaddr connip; + socklen_t taille; + char host[NI_MAXHOST]; + char serv[NI_MAXSERV]; + + taille=(socklen_t)(sizeof(connip)); + if (local==true) + status=getsockname(soc->handle,&connip,&taille); + else + status=getpeername(soc->handle,&connip,&taille); + switch (status) { + case -1 : //trouble to read socket data + switch(errno) { + case ENOTCONN : //other side just vanished + break; + default : + (void) rou_alert(0,"%s, Unable to socket data (local=%d, error=<%s>)", + OPEP,local,strerror(errno)); + break; + } + break; + default : + if (getnameinfo(&connip,taille,host,sizeof(host),serv,sizeof(serv),mode)==0) { + if (ip==true) + data=strdup(host); + else + data=strdup(serv); + } + break; } - else { - int flags; + } +return data; +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to close and release exchange socket */ +/* */ +/********************************************************/ +SOCPTR *soc_release(SOCPTR *socptr) - if ((flags=fcntl(newhandle,F_GETFL,0))<0) - (void) rou_core_dump("%s, Unable to get socket descripteur on " - "IP/PORT <%s/%s> (Bug? error=<%s>)", - OPEP,soc->ip,soc->port,strerror(errno)); - if ((flags=fcntl(newhandle,F_SETFL,flags|O_NONBLOCK|O_ASYNC))<0) - (void) rou_core_dump("%s, Unable to set socket descripteur on " - "IP/PORT <%s/%s> (Bug? error=<%s>)", +{ +#define OPEP "devsoc.c:soc_release" + +SOCTYP *soc; +int phase; +_Bool proceed; + +soc=(SOCTYP *)socptr; +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 0 : //checking if soc is available + if (soc==(SOCTYP *)0) { + (void) rou_core_dump("%s, socket descripteur missing (Bug?)",OPEP); + phase=999; //never reached + } + break; + case 1 : //shuting dow the TCP link + if (shutdown(soc->handle,SHUT_RDWR)<0) { + switch (errno) { + case ENOTCONN : //already disconnect by other side! + (void) rou_alert(0,"%s [%s:%s] Already disconnected (errno=<%s>)", + OPEP,soc->ip,soc->port,strerror(errno)); + break; + default : + (void) rou_alert(0,"%s unable to shutdown [%s:%s] (errno=<%s>)", + OPEP,soc->ip,soc->port,strerror(errno)); + break; + } + } + break; + case 2 : //closing connexion + if (close(soc->handle)<0) { + (void) rou_alert(0,"%s unable to close channel [%s:%s] properly " + "(errno=<%s>)", OPEP,soc->ip,soc->port,strerror(errno)); + } + break; + case 3 : //freeing the SSL contaxt + soc->ctx=ssl_releasectx(soc->ctx); + break; + case 4 : //fee memory used by socket + soc=freesocket(soc); + socptr=(SOCPTR *)soc; + break; + default : //SAFE guard + proceed=false; + break; } + phase++; } -return newhandle; +return socptr; #undef OPEP } /* @@ -444,12 +867,14 @@ if (mode!=modopen) { switch ((int)mode) { case true : (void) rou_modesubrou(mode); + (void) eml_modeunieml(mode); (void) prc_modeuniprc(mode); (void) ssl_modeunissl(mode); break; case false : (void) ssl_modeunissl(mode); (void) prc_modeuniprc(mode); + (void) eml_modeunieml(mode); (void) rou_modesubrou(mode); break; default : diff --git a/lib/devsoc.h b/lib/devsoc.h index d15fb63..fbbc8fa 100644 --- a/lib/devsoc.h +++ b/lib/devsoc.h @@ -18,7 +18,7 @@ typedef struct sockaddr SOCKADDR; //defining email protocol value. typedef enum { pro_smtp, //text SMTP protocol, in clear mode - pro_startls, //Text SMTP protocol, encrypted upon request + pro_starttls, //Text SMTP protocol, encrypted upon request pro_smtps, //Text SMTP protocol, text encrypted from start pro_unknwn //Protcole undefined }PROTYP; @@ -44,8 +44,26 @@ extern _Bool soc_openbinding(SOCPTR *socptr); //procedure to close ONE socket extern void soc_closebinding(SOCPTR *socptr); +//procedure to wait form character on contact +extern int soc_waitforchar(SOCPTR *socptr,TIMESPEC *attend); + +//procedure to return a char array with the available line +extern int soc_getnextline(SOCPTR *socptr,char **lineptr); + +//procedure to send a buffer contens on channel +extern int soc_writebuffer(SOCPTR *socptr,char *buffer,int tosend); + +//procedure to receive up to limit char from socket +extern void soc_receive(SOCPTR *socptr); + //procedure to wait and accept remote connexion -extern int soc_accept(SOCPTR *socptr,int pos); +extern SOCPTR *soc_accept(SOCPTR *socptr,int pos); + +//procedure to get information about addrbane and port +extern char *soc_getaddrinfo(SOCPTR *socptr,_Bool local,_Bool ip); + +//procedure to release/clsoe socket +extern SOCPTR *soc_release(SOCPTR *socptr); //homework to be done before starting/stopping module. extern int soc_modedevsoc(_Bool mode); diff --git a/lib/gestcp.c b/lib/gestcp.c index 7df10ce..b803f01 100644 --- a/lib/gestcp.c +++ b/lib/gestcp.c @@ -22,57 +22,6 @@ static _Bool modopen; //boolean module open/close /* - -*/ -/********************************************************/ -/* */ -/* Procedure to find the hostname related to an */ -/* socket, if local is true return the local */ -/* hostname else return the remote PID. */ -/* if trouble, return a NULL pointer. */ -/* */ -/********************************************************/ -static char *getaddrname(int handle,_Bool local) - -{ -#define OPEP "gestcp.c:soc_getaddrname" - -char *name; - -struct sockaddr connip; -socklen_t taille; -int status; -char host[NI_MAXHOST]; - -name=(char *)0; -taille=sizeof(connip); -status=-1; -if (local==true) { - if ((status=getsockname(handle,&connip,&taille))==0) { - if (getnameinfo(&connip,taille,host,sizeof(host),(char *)0,0,NI_NAMEREQD)==0) - name=strdup(host); - } - } -else { - if ((status=getpeername(handle,&connip,&taille))==0) { - if (getnameinfo(&connip,taille,host,sizeof(host),(char *)0,0,NI_NUMERICHOST)==0) - name=strdup(host); - } - } -if (status<0) { - switch (errno) { - case ENOTCONN : //other side just vanished - break; - default : - (void) rou_alert(0,"%s, Unable to find reverse (local=%d, error=<%s>)", - OPEP,local,strerror(errno)); - break; - } - } -return name; -#undef OPEP -} -/* ^L */ /********************************************************/ @@ -86,14 +35,6 @@ static CONTYP *freecontact(CONTYP *contact) #define OPEP "gesttcp.c:freecontact" if (contact!=(CONTYP *)0) { - if (contact->channel>=0) { - if (close(contact->channel)<0) { - (void) rou_alert(0,"%s unable to close channel properly (errno=<%s>)", - OPEP,strerror(errno)); - } - } - contact->carpile=rou_freestr(contact->carpile); - contact->EOL=rou_freestr(contact->EOL); contact->peerip=rou_freestr(contact->peerip); contact->locname=rou_freestr(contact->locname); (void) free(contact); @@ -107,121 +48,6 @@ return contact; */ /********************************************************/ /* */ -/* Procedure to check if char are available on */ -/* soc interface. */ -/* comming from the remote end. */ -/* */ -/********************************************************/ -static int waitforchar(CONTYP *tact,TIMESPEC *attend) - -{ -struct pollfd polling[1]; - -polling[0].events=POLLIN|POLLPRI; -polling[0].revents=(short)0; -polling[0].fd=tact->channel; -return ppoll(polling,1,attend,(sigset_t *)0); -} -/* -^L -*/ -/********************************************************/ -/* */ -/* Procedure to read the maximun of characters */ -/* comming from the remote end. */ -/* */ -/********************************************************/ -static void readmaxchar(CONTYP *tact) - -{ -int limit; - -limit=(tact->maxcarin-tact->carin)-1; -if (limit>0) { - int got; - - got=recv(tact->channel,tact->carpile+tact->carin,limit,MSG_DONTWAIT); - (void) printf("readmax got '%d' char\n",got); - switch (got) { - case -1 : //do not block - if (errno==EWOULDBLOCK) - errno=EAGAIN; - switch (errno) { - case EAGAIN : //no char available - break; - default : - (void) fprintf(stderr,"JMPDBG readmax error=<%s>\n",strerror(errno)); - break; - } - break; - case 0 : //EOL? - break; - default : //we got som char from remote - tact->carin+=got; //managing carpile - tact->carpile[tact->carin]='\000'; - break; - } - } -} -/* -^L -*/ -/********************************************************/ -/* */ -/* Procedure to locate CRLF within the current line*/ -/* assigne memory and store carpile contents */ -/* */ -/********************************************************/ -static int getnextline(CONTYP *tact,char **lineptr) - -{ -int got; -char *eol; -int phase; -_Bool proceed; - -*lineptr=(char *)0; -got=0; -eol=(char *)0; -phase=0; -proceed=true; -while (proceed==true) { - switch (phase) { - case 0 : //Do we have dat in carpile - if (tact->carin==0) - phase=999; //No char,no need to check for line - break; - case 1 : //Do we have a CRLF - eol=strstr(tact->carpile,tact->EOL); - if (eol==(char *)0) - phase=999; //No End Of Line yet - break; - case 2 : //duplicating carpile - *lineptr=calloc(tact->carin+1,sizeof(char)); - *eol='\000'; - (void) strcpy(*lineptr,tact->carpile); - (void) strcat(*lineptr,tact->EOL); - got=strlen(*lineptr); - break; - case 3 : //managing carpile - tact->carin-=strlen(*lineptr); - if (tact->carin>0) - (void) memmove(tact->carpile,tact->carpile+strlen(*lineptr),tact->carin); - tact->carpile[tact->carin]='\000'; - break; - default : //SAFE guard - proceed=false; - break; - } - phase++; - } -return got; -} -/* -^L -*/ -/********************************************************/ -/* */ /* Procedure to read char from remote peer, wait */ /* for a CRLF AS EOL. */ /* */ @@ -247,16 +73,16 @@ while (proceed==true) { } break; case 1 : //get nextline - if ((got=getnextline(contact,lineptr))>0) + if ((got=soc_getnextline(contact->socptr,lineptr))>0) phase=999; //we got a line. break; case 2 : //waiting for new character presence - switch (waitforchar(contact,attend)) { + switch (soc_waitforchar(contact->socptr,attend)) { case -1 : //trouble? signal? case 0 : //normal time out break; //no need to read line default : //char available - (void) readmaxchar(contact); + (void) soc_receive(contact->socptr); phase=0; //check for new line break; } @@ -275,37 +101,18 @@ return got; */ /********************************************************/ /* */ -/* Procedure to send data to a tcp socket. */ -/* return the number of character transmitted, is */ -/* unable to send char return -1; */ +/* Procedure to write buffer on the socket output */ +/* return the number of char sent on channel. */ /* */ /********************************************************/ -PUBLIC int tcp_write(CONTYP *contact,char *buffer,int parnum) +PUBLIC int tcp_write(CONTYP *contact,char *buffer,int tosend) { int sent; -int got; sent=-1; -got=recv(contact->channel,(char *)0,0,MSG_PEEK); -switch (got) { - case -1 : - if (errno==EWOULDBLOCK) - errno=EAGAIN; - switch (errno) { - case EAGAIN : - sent=send(contact->channel,buffer,parnum,0); - break; - default : - (void) fprintf(stderr,"Got '%02d' error=<%s> (errno='%d')\n", - got,strerror(errno),errno); - break; - } - break; - default : - (void) fprintf(stderr,"Got '%02d'\n",got); - break; - } +if (contact!=(CONTYP *)0) + sent=soc_writebuffer(contact->socptr,buffer,tosend); return sent; } /* @@ -341,20 +148,15 @@ while (proceed==true) { break; case 1 : //waiting from contact contact=calloc(1,sizeof(CONTYP)); - contact->socptr=socptr; - contact->maxcarin=MXCARIN; - contact->carin=0; - contact->EOL=strdup(CRLF); - contact->carpile=(char *)calloc(contact->maxcarin,sizeof(char)); - if ((contact->channel=soc_accept(socptr,pos))<0) { + if ((contact->socptr=soc_accept(socptr,pos))==(SOCPTR *)0) { (void) rou_alert(0,"%s Unable to open contact",OPEP); contact=freecontact(contact); phase=999; //no contact } break; case 2 : //check socket components - contact->locname=getaddrname(contact->channel,true); - contact->peerip=getaddrname(contact->channel,false); + contact->locname=soc_getaddrinfo(contact->socptr,true,false); + contact->peerip=soc_getaddrinfo(contact->socptr,false,false); if ((contact->locname==(char *)0)||(contact->peerip==(char *)0)) { (void) rou_alert(0,"%s Unable to establish contact entities",OPEP); contact=freecontact(contact); @@ -421,18 +223,7 @@ while (proceed==true) { break; case 1 : //properly closing remote contact (void) rou_alert(0,"Contact with IP=<%s> Exiting",contact->peerip); - if (shutdown(contact->channel,SHUT_RDWR)<0) { - switch (errno) { - case ENOTCONN : //already disconnect by other side! - (void) rou_alert(0,"%s Already disconnected (errno=<%s>)", - OPEP,strerror(errno)); - break; - default : - (void) rou_alert(0,"%s unable to shutdown (errno=<%s>)", - OPEP,strerror(errno)); - break; - } - } + contact->socptr=soc_release(contact->socptr); break; case 2 : //freeing contact memory contact=freecontact(contact); diff --git a/lib/gestcp.h b/lib/gestcp.h index 2191062..6d985b1 100644 --- a/lib/gestcp.h +++ b/lib/gestcp.h @@ -13,21 +13,16 @@ #include "devsoc.h" typedef struct { - int channel; //exchange channel handle + SOCPTR *socptr; //established contact context char *locname; //socket local hostname char *peerip; //socket remote peer IP - SOCPTR *socptr; //established contact context - int maxcarin; //absolute number within carin - char *EOL; //End of line marker - int carin; //number of char within incpt; - char *carpile; //area to store incoming char }CONTYP; //read a line from contact up to CRLF extern int tcp_getline(CONTYP *contact,TIMESPEC *attend,char **lineptr); //Transmit formated data to the contact channel -extern int tcp_write(CONTYP *contact,char *buffer,int parnum); +extern int tcp_write(CONTYP *contact,char *buffer,int tosend); //wait for an incoming contact extern CONTYP *tcp_getcontact(SOCPTR *socptr,int pos); diff --git a/lib/modrec.c b/lib/modrec.c index 977646e..4acf4b2 100644 --- a/lib/modrec.c +++ b/lib/modrec.c @@ -50,11 +50,10 @@ while (proceed==true) { if ((contact=tcp_getcontact(socptr,pos))==(CONTYP *)0) phase=999; //No contact! break; - case 1 : //forking process - printf("New client connected: %d\n",contact->channel); + case 1 : //within forked process + printf("New client [%s] connected\n",contact->peerip); break; case 2 : //do contact - printf("Client channel=%d (pid=%d)\n",contact->channel,getpid()); for (int i=0;i -#include -#include #include #include "subrou.h" @@ -15,6 +13,95 @@ static _Bool modopen; //module open/close status +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to realease all SSL contaxt */ +/* */ +/********************************************************/ +PUBLIC SSL_CTX *ssl_releasectx(SSL_CTX *ctx) + +{ +(void) SSL_CTX_free(ctx); +return (SSL_CTX *)0; +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to establish a working SSL context */ +/* Return SLL context or a NULL pointer */ +/* */ +/********************************************************/ +PUBLIC SSL_CTX *ssl_getctx(_Bool server_mode) + +{ +#define OPEP "unissl.c:ssl_getctx" + +SSL_CTX *ctx; +const SSL_METHOD *(*tls_methode)(); +const char *certpub[2]; +int phase; +_Bool proceed; + +ctx=(SSL_CTX *)0; +tls_methode=TLS_client_method; +if (server_mode==true) + tls_methode=TLS_server_method; +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 0 : //Setting inital context + if ((ctx=SSL_CTX_new(tls_methode()))!=(SSL_CTX *)0) { + char reason[200]; + + (void) ERR_error_string(ERR_get_error(),reason); + (void) rou_core_dump("%s, Unable to set the SSL context err=<%s> (system?)", + OPEP,reason); + phase=999; //Useless, cire dump never return + } + break; + case 1 : //getting certificat name + certpub[0]="./cert.pem"; //JMPDBG test + certpub[1]="./key.pem"; //JMPDBG test + break; + case 2 : //set certificate + if (SSL_CTX_use_certificate_file(ctx,certpub[0],SSL_FILETYPE_PEM)!=1) { + char reason[200]; + + (void) ERR_error_string(ERR_get_error(),reason); + (void) rou_alert(0,"Unable to use certificate <%s> (error=<%s>)", + certpub[0],reason); + (void) SSL_CTX_free(ctx); + ctx=(SSL_CTX *)0; + phase=999; + } + break; + case 3 : //set key + if (SSL_CTX_use_PrivateKey_file(ctx,certpub[1],SSL_FILETYPE_PEM)!=1) { + char reason[200]; + + (void) ERR_error_string(ERR_get_error(),reason); + (void) rou_alert(0,"Unable to use certificate key <%s> (error=<%s>)", + certpub[0],reason); + (void) SSL_CTX_free(ctx); + ctx=(SSL_CTX *)0; + phase=999; + } + break; + default : //SAFE guard + proceed=false; + break; + } + phase++; + } +return ctx; +#undef OPEP +} /* ^L */ diff --git a/lib/unissl.h b/lib/unissl.h index ef8d25b..018b6c9 100644 --- a/lib/unissl.h +++ b/lib/unissl.h @@ -7,6 +7,15 @@ #ifndef UNISSL #define UNISSL +#include +#include + +//releasing current SSL context; +extern SSL_CTX *ssl_releasectx(SSL_CTX *ctx); + +//establishing SSL working context +extern SSL_CTX *ssl_getctx(_Bool server_mode); + //homework to be done before starting/stopping module. extern int ssl_modeunissl(_Bool mode); -- 2.47.3