gestcp.h: \
subrou.h \
- devsoc.h
+ devlog.h devsoc.h
uniprc.h: \
subrou.h
/* Log management implementation module */
/* */
/********************************************************/
+#include <errno.h>
+#include <malloc.h>
#include <stdbool.h>
#include <stdio.h>
+#include <string.h>
#include "subrou.h"
#include "uniprc.h"
#include "devlog.h"
-static _Bool modopen; //boolean module open/close
+#define JRLDIR "/var/spool/clement/logs/"
+
+
+typedef struct {
+ char *filename; //the log filename
+ FILE *file; //The log file pointer
+ TIMESPEC start; //log start time
+ }LOGTYP;
+
+static _Bool modopen; //boolean module open/close
+/*
+^L
+*/
+/********************************************************/
+/* */
+/* Procedure to free reference to a log device */
+/* */
+/********************************************************/
+static LOGTYP *freelog(LOGTYP *log)
+
+{
+if (log!=(LOGTYP *)0) {
+ log->filename=rou_freestr(log->filename);
+ (void) free(log);
+ log=(LOGTYP *)0;
+ }
+return log;
+}
+/*
+^L
+*/
+/********************************************************/
+/* */
+/* Procedure to open a session log to collect all */
+/* exchange with remote SMTP client. */
+/* return a NULL file pointeur if trouble. */
+/* */
+/********************************************************/
+PUBLIC LOGPTR *log_openlog(char *logname)
+
+{
+#define OPEP "devlog.c:log_openlog"
+
+LOGTYP *log;
+int phase;
+int proceed;
+
+log=(LOGTYP *)0;
+phase=0;
+proceed=true;
+while (proceed==true) {
+ switch (phase) {
+ case 0 : //do we have a log name?
+ if (logname==(char *)0) {
+ (void) rou_alert(0,"%s logname is missing (Bug!?)",OPEP);
+ phase=999;
+ }
+ break;
+ case 1 : //generating log file name
+ log=(LOGTYP *)calloc(1,sizeof(LOGTYP));
+ log->filename=rou_apppath(JRLDIR);
+ log->filename=(char *)realloc(log->filename,
+ strlen(log->filename)+strlen(logname)+10);
+ (void) strcat(log->filename,logname);
+ (void) strcat(log->filename,".jrl");
+
+ break;
+ case 2 : //opening the log file
+ if ((log->file=fopen(log->filename,"w"))==(FILE *)0) {
+ (void) rou_alert(0,"%s Unable to open file <%s> (error=<%s>)",
+ OPEP,log->filename,strerror(errno));
+ log=freelog(log);
+ }
+ break;
+ default : //SAFE guard
+ proceed=false;
+ break;
+ }
+ phase++;
+ }
+return (LOGPTR *)log;
+#undef OPEP
+}
+/*
+^L
+*/
+/********************************************************/
+/* */
+/* Procedure to close a session log */
+/* return the close status. */
+/* */
+/********************************************************/
+PUBLIC LOGPTR *log_closelog(LOGPTR *logptr)
+
+{
+#define OPEP "devlog.c:log_closelog"
+
+LOGTYP *log;
+int phase;
+int proceed;
+
+log=(LOGTYP *)logptr;
+phase=0;
+proceed=true;
+while (proceed==true) {
+ switch (phase) {
+ case 0 : //do we have a log name?
+ if (log==(LOGTYP *)0) {
+ (void) rou_alert(0,"%s log pointer is NULL (Bug!?)",OPEP);
+ phase=999;
+ }
+ break;
+ case 1 : //do we have a log name?
+ if (fclose(log->file)!=0) {
+ (void) rou_alert(0,"%s Unable to close log file <%s> (error=<%s>)",
+ OPEP,log->filename,strerror(errno));
+ phase=999;
+ }
+ break;
+ default : //SAFE guard
+ logptr=freelog(log);
+ proceed=false;
+ break;
+ }
+ phase++;
+ }
+return logptr;
+#undef OPEP
+}
+/*
+^L
+*/
+/********************************************************/
+/* */
+/* Procedure to insert a formated string within */
+/* log file. */
+/* */
+/********************************************************/
+PUBLIC int log_fprintlog(LOGPTR *logptr,const char *format,...)
+
+{
+#define OPEP "devlog.c:log_fprintlog"
+int taille;
+LOGTYP *log;
+char chrono[20];
+char *line;
+va_list args;
+int phase;
+int proceed;
+
+taille=0;
+log=(LOGTYP *)logptr;
+(void) strcpy(chrono,"");
+line=(char *)0;
+va_start(args,format);
+phase=0;
+proceed=true;
+while (proceed==true) {
+ switch (phase) {
+ case 0 : //do we have a log name?
+ if (log==(LOGTYP *)0) {
+ (void) rou_alert(0,"%s log pointer is NULL (Bug!?)",OPEP);
+ phase=999;
+ }
+ break;
+ case 1 : //set time marker within log
+ if (log->start.tv_sec==0) {
+ (void) clock_gettime(CLOCK_REALTIME,&(log->start));
+ (void) snprintf(chrono,sizeof(chrono),"00:00:00.000");
+ }
+ else {
+ unsigned int delta;
+
+ delta=rou_getdifftime(&(log->start));
+ (void) snprintf(chrono,sizeof(chrono)," +%02d.%03d",
+ delta/1000,delta%1000);
+ }
+ break;
+ case 2 : //formating the line
+ if ((taille=rou_vasprintf(&line,format,args))<=0) {
+ (void) rou_alert(0,"%s Unable to format <%s> (Bug!?)",OPEP,format);
+ phase=999;
+ }
+ break;
+ case 3 : //string the formated line within logs
+ (void) fprintf(log->file,"%s %s\n",chrono,line);
+ line=rou_freestr(line);
+ break;
+ default : //SAFE guard
+ proceed=false;
+ break;
+ }
+ phase++;
+ }
+va_end(args);
+return taille;
+#undef OPEP
+}
/*
^L
*/
#ifndef DEVLOG
#define DEVLOG
+#include <stdio.h>
+
+typedef void LOGPTR;
+
+//procedure to open a session log
+extern LOGPTR *log_openlog(char *logname);
+
+//procedure to close a previously open session log
+extern LOGPTR *log_closelog(LOGPTR *logptr);
+
+//procedure to write a sequence within the current log
+extern int log_fprintlog(LOGPTR *logptr,const char *format,...);
+
+//procedure to merge session log contents to
+//current daily log
+extern int log_mergelog(char *logname);
+
//homework to be done before starting/stopping module.
extern int log_modedevlog(_Bool mode);
/* for local or remote socket. */
/* */
/********************************************************/
-PUBLIC char *soc_getaddrinfo(SOCPTR *socptr,_Bool local,_Bool ip)
+PUBLIC char *soc_getaddrinfo(SOCPTR *socptr,_Bool local,_Bool getname)
{
#define OPEP "devsoc.c:soc_getaddrinfo"
data=(char *)0;
soc=(SOCTYP *)socptr;
-mode=NI_NAMEREQD;
-if (local==false)
- mode=NI_NUMERICHOST;
-mode|=NI_NUMERICSERV;
+mode=NI_NUMERICSERV;
+switch (getname) {
+ case true :
+ mode|=NI_NAMEREQD;
+ break;
+ case false :
+ mode|=NI_NUMERICHOST;
+ break;
+ }
if (soc!=(SOCTYP *)0) {
int status;
struct sockaddr connip;
char host[NI_MAXHOST];
char serv[NI_MAXSERV];
+ (void) strcpy(host,"Unknown IP");
+ (void) strcpy(serv,"Unknown service");
taille=(socklen_t)(sizeof(connip));
if (local==true)
status=getsockname(soc->handle,&connip,&taille);
break;
}
break;
- default :
- if (getnameinfo(&connip,taille,host,sizeof(host),serv,sizeof(serv),mode)==0) {
- if (ip==true)
+ case 0 : //NO trouble to read socket data
+ status=getnameinfo(&connip,taille,host,sizeof(host),serv,sizeof(serv),mode);
+ (void) printf("JMPDBG getname status='%d', local='%d' getname='%d'\n",
+ status,local,getname);
+ switch (status) {
+ case 0 : //everything fine
+ (void) printf("JMPDBG host=<%s>\n",host);
+ break;
+ case EAI_AGAIN :
+ case EAI_NONAME :
+ if (getname==true)
+ (void) strcpy(host,"No.Reverse");
+ default :
+ (void) rou_alert(0,"%s, Unable to get name (local=%d, error=<%s>)",
+ OPEP,local,strerror(errno));
+ break;
+ }
+ break;
+ default : //Unexpected touble to read socket
+ (void) rou_alert(0,"%s, status=%d Unexpected (local=%d, error=<%s>) (Bug?)",
+ OPEP,status,local,strerror(errno));
+ break;
+ }
+ switch (local) {
+ case true :
+ switch (getname) {
+ case true :
data=strdup(host);
- else
+ break;
+ case false :
data=strdup(serv);
+ break;
}
break;
+ case false :
+ data=strdup(host);
+ break;
}
}
return data;
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);
+extern char *soc_getaddrinfo(SOCPTR *socptr,_Bool local,_Bool getname);
//procedure to release/clsoe socket
extern SOCPTR *soc_release(SOCPTR *socptr);
static CONTYP *freecontact(CONTYP *contact)
{
-#define OPEP "gesttcp.c:freecontact"
+#define OPEP "gestcp.c:freecontact"
if (contact!=(CONTYP *)0) {
+ contact->log=log_closelog(contact->log);
contact->cursesid=rou_freestr(contact->cursesid);
contact->mainsesid=rou_freestr(contact->mainsesid);
contact->fqdn=rou_freestr(contact->fqdn);
+ contact->peername=rou_freestr(contact->peername);
contact->peerip=rou_freestr(contact->peerip);
contact->locname=rou_freestr(contact->locname);
contact->locserv=rou_freestr(contact->locserv);
phase=999; //no contact
}
break;
- case 2 : //check socket components
- contact->locname=soc_getaddrinfo(contact->socptr,true,true);
- contact->locserv=soc_getaddrinfo(contact->socptr,true,false);
- contact->peerip=soc_getaddrinfo(contact->socptr,false,true);
+ case 2 : //Preparing contact
contact->mainsesid=eml_getmainsesid();
contact->cursesid=eml_getcursesid(contact->mainsesid,contact->numreset);
+ contact->locname=soc_getaddrinfo(contact->socptr,true,true);
+ contact->locserv=soc_getaddrinfo(contact->socptr,true,false);
+ contact->peername=soc_getaddrinfo(contact->socptr,false,true);
+ contact->peerip=soc_getaddrinfo(contact->socptr,false,false);
+ contact->log=log_openlog(contact->mainsesid);
+ break;
+ case 3 : //check contact validity
if ((contact->locname==(char *)0)||(contact->peerip==(char *)0)) {
(void) rou_alert(0,"%s Unable to establish contact entities",OPEP);
contact=freecontact(contact);
phase=999; //no identity
}
break;
- case 3 : //contact is good, then sending a signon
+ case 4 : //contact is good, then sending a signon
+ (void) log_fprintlog(contact->log,"SID: %s -> Contact open",
+ contact->mainsesid);
if (tcp_signon(contact)<=0) {
contact=freecontact(contact);
phase=999; //no contact
#include <stdbool.h>
#include "subrou.h"
+#include "devlog.h"
#include "devsoc.h"
typedef struct {
char *locname; //socket local hostname
char *locserv; //local service port
char *peerip; //socket remote peer IP
+ char *peername; //socket remote peer FQDN
int numreset; //number of SMTP reset received
char *mainsesid;//session main ID
char *cursesid; //current session ID
+ LOGPTR *log; //reference to session log
}CONTYP;
//read a line from contact up to CRLF
#include "subrou.h"
#include "unieml.h"
+#include "devlog.h"
#include "lvleml.h"
{
va_list args;
-char line[300];
+char *line;
va_start(args,fmt);
-(void) vsnprintf(line,sizeof(line),fmt,args);
-(void) tcp_write(contact,line,strlen(line));
-(void) tcp_write(contact,CRLF,strlen(CRLF));
+line=(char *)0;
+if (rou_vasprintf(&line,fmt,args)>0) {
+ (void) tcp_write(contact,line,strlen(line));
+ (void) tcp_write(contact,CRLF,strlen(CRLF));
+ }
va_end(args);
}
/*
case 1 : //thereis an FQDN
contact->fqdn=rou_freestr(contact->fqdn);
contact->fqdn=strdup(parameter);
- (void) transmit(contact,"%d-%s ready, your IP=[%s]",
- CMDOK,contact->locname,contact->peerip);
+ (void) transmit(contact,"%d-%s ready, your IP=[%s/%s]",
+ CMDOK,contact->locname,
+ contact->peerip,contact->peername);
(void) transmit(contact,"%d-SIZE %ld",CMDOK,MXMSIZE);
if (contact->tlsok==true)
strstart++;
attend.tv_sec=60;
attend.tv_nsec=0;
status=tcp_getline(contact,&attend,&line);
- parameter=strchr(line,' ');
- if (parameter==(char *)0)
- parameter=strchr(line,'\t');
- if (parameter!=(char *)0) {
- *parameter='\000';
- parameter++;
- while ((*parameter==' ')||(*parameter=='\t'))
- parameter++;
- }
if (status<=0) //timeout or trouble?
break; //no need to go further
+ if (line!=(char *)0) {
+ parameter=strchr(line,' ');
+ if (parameter==(char *)0)
+ parameter=strchr(line,'\t');
+ if (parameter!=(char *)0) {
+ *parameter='\000';
+ parameter++;
+ while ((*parameter==' ')||(*parameter=='\t'))
+ parameter++;
+ }
+ }
switch (eml_getcode(line)) {
case c_helo : //HELO SMTP protocol
proceed=dohelo(contact,line,parameter);
status=0;
if (mode!=modopen) {
- (void) rou_modesubrou(mode);
switch ((int)mode) {
case true :
+ (void) rou_modesubrou(mode);
+ (void) eml_modeunieml(mode);
+ (void) log_modedevlog(mode);
break;
case false :
+ (void) log_modedevlog(mode);
+ (void) eml_modeunieml(mode);
+ (void) rou_modesubrou(mode);
break;
default :
(void) fprintf(stderr,"Calling %s with wrong mode='%d' (Bug?!):",
(void) prc_settitle("Processing incoming contact from [%s] on [%s:%s]",
contact->peerip,contact->locname,contact->locserv);
(void) rou_checkleak(true);
- printf("New client [%s] connected pid='%05d'\n",contact->peerip,getpid());
+ printf("New client [%s/%s] connected pid='%05d'\n",
+ contact->peerip,contact->peername,getpid());
break;
case 2 : //do contact
switch (eml_docontact(contact)) {
//version definition
#define VERSION "0.4.1"
-#define RELEASE "4"
+#define RELEASE "5"
//Public variables
PUBLIC int debug=0; //debug level
/********************************************************/
/* */
/* Procedure to assign enough memory to format */
+/* a string with va_list parameter. */
+/* Known as vasprintf in GNU_SOURCE. */
+/* */
+/********************************************************/
+PUBLIC int rou_vasprintf(char **str,const char *fmt,va_list ap)
+
+{
+int taille;
+va_list sup;
+char loc[10];
+
+(void) va_copy(sup,ap);
+if ((taille=vsnprintf(loc,4,fmt,ap))>0) {
+ *str=calloc(taille+2,sizeof(char));
+ taille=vsnprintf(*str,taille+1,fmt,sup);
+ }
+return taille;
+}
+/*
+\f
+*/
+/********************************************************/
+/* */
+/* Procedure to assign enough memory to format */
/* a string. */
/* Known as asprintf in GNU_SOURCE. */
/* */
*/
/********************************************************/
/* */
+/* Procedure to return the time difference between */
+/* current real-time at nano-second level and */
+/* time reference. */
+/* time difference unit is millisec. */
+/* */
+/********************************************************/
+PUBLIC unsigned int rou_getdifftime(TIMESPEC *start)
+
+{
+unsigned int result;
+
+result=0;
+if (start!=(TIMESPEC *)0) {
+ TIMESPEC current;
+
+ (void) clock_gettime(CLOCK_REALTIME,¤t);
+ result=(current.tv_sec-start->tv_sec)*1000;
+ result+=(current.tv_nsec-start->tv_nsec)/1000000;
+ }
+return result;
+}
+/*
+\f
+*/
+/********************************************************/
+/* */
/* Procedure to return the current time */
/* expressed with a millisecond precision starting */
/* from the firt time it was called. */
//open/close memory leak detector.
extern void rou_checkleak(_Bool onoff);
+//procedure to assign memory according a format and va list
+extern int rou_vasprintf(char **str,const char *fmt,va_list ap);
+
//procedure to assign memory according a format and parameter list
extern int rou_asprintf(char **str,const char *fmt,...);
+//procedure to get the time difference between the current
+//time and a TIMESPEC starttime
+extern unsigned rou_getdifftime(TIMESPEC *start);
+
//procedure to return the current number of milli-second
extern unsigned int rou_getmillisec();