Commit 5899a303 authored by rswindell's avatar rswindell

The problem: the sysop (me) is not notified of critical errors (e.g....

The problem: the sysop (me) is not notified of critical errors (e.g. synchro.net zone file problems) in a timely manner.
Part of the solution: notify a configured user (e.g. user #1) via short-message/telegram and email/netmail logged-errors when messages of a configured severity (e.g. "Critical") are logged.
The second part of the solution (coming next) will be allowing timed events to log a message of a configurable severity logged when the event fails (returns a non-zero error level to sbbs).

I'm saving the error-notification-user-number and log-severity as part of the node.cnf file because:
- that's where the validation user number is already set
- I can conceive of a large system were certain node ranges (different instances of sbbs) might want different operators to be notified of logged-errors

This also means I eliminated all the legacy com port/modem stuff from the end of the node.cnf file. None of that is used in sbbs v3.

Also included in this commit are improvements around logging:
- reduce the severity of UDP recvfrom failures in services
- a more detailed log message when the mail server successfully delivers an email (via SMTP) - easier to answer the question: was that email you/they sent delivered successfully?
parent 277bbde6
......@@ -157,7 +157,7 @@ static int lprintf(int level, const char *fmt, ...)
if(level <= LOG_ERR) {
char errmsg[sizeof(sbuf)+16];
SAFEPRINTF(errmsg, "ftp %s", sbuf);
errorlog(&scfg, startup==NULL ? NULL:startup->host_name, errmsg);
errorlog(&scfg, level, startup==NULL ? NULL:startup->host_name, errmsg);
if(startup!=NULL && startup->errormsg!=NULL)
startup->errormsg(startup->cbdata,level,errmsg);
}
......
......@@ -117,7 +117,7 @@ extern "C" BOOL DLLCALL spamlog(scfg_t* cfg, char* prot, char* action
return true;
}
extern "C" int DLLCALL errorlog(scfg_t* cfg, const char* host, const char* text)
extern "C" int DLLCALL errorlog(scfg_t* cfg, int level, const char* host, const char* text)
{
FILE* fp;
char buf[128];
......@@ -136,6 +136,11 @@ extern "C" int DLLCALL errorlog(scfg_t* cfg, const char* host, const char* text)
,log_line_ending
);
fclose(fp);
if(cfg->node_erruser && level >= cfg->node_errlevel) {
char subject[128];
SAFEPRINTF2(subject, "%s %sERROR occurred", host == NULL ? "" : host, level <= LOG_CRIT ? "CRITICAL " : "");
notify(cfg, cfg->node_erruser, subject, text);
}
return 0;
}
......
......@@ -181,7 +181,7 @@ static int lprintf(int level, const char *fmt, ...)
if(level <= LOG_ERR) {
char errmsg[sizeof(sbuf)+16];
SAFEPRINTF(errmsg, "mail %s", sbuf);
errorlog(&scfg,startup==NULL ? NULL:startup->host_name,errmsg), stats.errors++;
errorlog(&scfg, level, startup==NULL ? NULL:startup->host_name,errmsg), stats.errors++;
if(startup!=NULL && startup->errormsg!=NULL)
startup->errormsg(startup->cbdata,level,errmsg);
}
......@@ -5787,7 +5787,9 @@ static void sendmail_thread(void* arg)
continue;
}
}
lprintf(LOG_INFO,"%04d %s message transfer complete (%lu bytes, %lu lines)", sock, prot, bytes, lines);
lprintf(LOG_INFO, "%04d %s Successfully sent message #%u (%lu bytes, %lu lines) from %s%s %s to %s [%s]"
,sock, prot, msg.hdr.number, bytes, lines, msg.from, fromext, fromaddr
,msg.to, toaddr);
/* Now lets mark this message for deletion without corrupting the index */
if((msg.hdr.netattr & MSG_KILLSENT) || msg.from_ext == NULL)
......@@ -5800,13 +5802,13 @@ static void sendmail_thread(void* arg)
if(msg.hdr.auxattr&MSG_FILEATTACH)
delfattach(&scfg,&msg);
if(msg.from_agent==AGENT_PERSON && !(startup->options&MAIL_OPT_NO_AUTO_EXEMPT))
exempt_email_addr("SEND Auto-exempting",msg.from,fromext,fromaddr,toaddr);
/* QUIT */
sockprintf(sock,prot,session,"QUIT");
sockgetrsp(sock,prot,session,"221", buf, sizeof(buf));
mail_close_socket(&sock, &session);
if(msg.from_agent==AGENT_PERSON && !(startup->options&MAIL_OPT_NO_AUTO_EXEMPT))
exempt_email_addr("SEND Auto-exempting",msg.from,fromext,fromaddr,toaddr);
}
status(STATUS_WFC);
/* Free up resources here */
......
......@@ -207,7 +207,7 @@ int lputs(int level, const char* str)
if(level <= LOG_ERR) {
char errmsg[1024];
SAFEPRINTF(errmsg, "term %s", str);
errorlog(&scfg,startup==NULL ? NULL:startup->host_name, errmsg);
errorlog(&scfg, level, startup==NULL ? NULL:startup->host_name, errmsg);
if(startup!=NULL && startup->errormsg!=NULL)
startup->errormsg(startup->cbdata,level,errmsg);
}
......@@ -231,7 +231,7 @@ int eputs(int level, const char *str)
if(level <= LOG_ERR) {
char errmsg[1024];
SAFEPRINTF(errmsg, "evnt %s", str);
errorlog(&scfg,startup==NULL ? NULL:startup->host_name, errmsg);
errorlog(&scfg, level, startup==NULL ? NULL:startup->host_name, errmsg);
if(startup!=NULL && startup->errormsg!=NULL)
startup->errormsg(startup->cbdata, level, errmsg);
}
......
......@@ -588,3 +588,50 @@ extern "C" int DLLCALL postpoll(scfg_t* cfg, smb_t* smb, smbmsg_t* msg)
return smb_addpoll(smb, msg, smb_storage_mode(cfg, smb));
}
// Send an email and a short-message to a local user about something important (e.g. a system error)
extern "C" int DLLCALL notify(scfg_t* cfg, uint usernumber, const char* subject, const char* text)
{
int i;
smb_t smb = {0};
uint16_t xlat;
int storage;
long dupechk_hashes;
uint16_t agent = AGENT_PROCESS;
uint16_t nettype = NET_UNKNOWN;
smbmsg_t msg = {0};
user_t user = {0};
char str[128];
user.number = usernumber;
if((i = getuserdat(cfg, &user)) != 0)
return i;
msg.hdr.when_imported.time = time32(NULL);
msg.hdr.when_imported.zone = sys_timezone(cfg);
msg.hdr.when_written = msg.hdr.when_imported;
smb_hfield(&msg, SENDERAGENT, sizeof(agent), &agent);
smb_hfield_str(&msg, SENDER, cfg->sys_name);
smb_hfield_str(&msg, RECIPIENT, user.alias);
if(cfg->sys_misc&SM_FWDTONET && user.misc&NETMAIL && user.netmail[0]) {
smb_hfield_netaddr(&msg, RECIPIENTNETADDR, user.netmail, &nettype);
smb_hfield_bin(&msg, RECIPIENTNETTYPE, nettype);
} else {
SAFEPRINTF(str, "%u", usernumber);
smb_hfield_str(&msg, RECIPIENTEXT, str);
}
smb_hfield_str(&msg, SUBJECT, subject);
add_msg_ids(cfg, &smb, &msg, /* remsg: */NULL);
if(msgbase_open(cfg, &smb, INVALID_SUB, &storage, &dupechk_hashes, &xlat) == SMB_SUCCESS) {
smb_addmsg(&smb, &msg, storage, dupechk_hashes, xlat, (uchar*)text, /* tail: */NULL);
smb_close(&smb);
}
smb_freemsgmem(&msg);
char smsg[1024];
safe_snprintf(smsg, sizeof(smsg),"\1n\1h%s \1r%s:\r\n%s\1n\r\n"
,timestr(cfg, msg.hdr.when_imported.time, str)
,subject
,text);
return putsmsg(cfg, usernumber, smsg);
}
......@@ -1175,6 +1175,7 @@ extern "C" {
DLLEXPORT int DLLCALL closepoll(scfg_t*, smb_t*, uint32_t msgnum, const char* username);
DLLEXPORT void DLLCALL signal_sub_sem(scfg_t*, uint subnum);
DLLEXPORT int DLLCALL msg_client_hfields(smbmsg_t*, client_t*);
DLLEXPORT int DLLCALL notify(scfg_t*, uint usernumber, const char* subject, const char* msg);
/* filedat.c */
DLLEXPORT BOOL DLLCALL getfileixb(scfg_t* cfg, file_t* f);
......@@ -1269,7 +1270,7 @@ extern "C" {
DLLEXPORT int DLLCALL smb_open_sub(scfg_t*, smb_t*, unsigned int subnum);
/* logfile.cpp */
DLLEXPORT int DLLCALL errorlog(scfg_t* cfg, const char* host, const char* text);
DLLEXPORT int DLLCALL errorlog(scfg_t* cfg, int level, const char* host, const char* text);
DLLEXPORT BOOL DLLCALL hacklog(scfg_t* cfg, const char* prot, const char* user, const char* text
,const char* host, union xp_sockaddr* addr);
......
......@@ -481,6 +481,8 @@ typedef struct
uchar node_scrnblank; /* Min of inactivity for blank screen */
uint32_t node_misc; /* Misc bits for node setup */
uint16_t node_valuser; /* User validation mail goes to */
uint16_t node_erruser; /* User error messages goes to */
uchar node_errlevel; /* Log level threshold to notify user (node_erruser) */
uint16_t node_ivt; /* Time-slice APIs */
uchar node_swap; /* Swap types allowed */
char node_swapdir[LEN_DIR+1]; /* Swap directory */
......
......@@ -59,7 +59,6 @@ BOOL read_node_cfg(scfg_t* cfg, char* error)
{
char c,str[MAX_PATH+1],fname[13];
int i;
int16_t n;
long offset=0;
FILE *instream;
......@@ -124,49 +123,9 @@ BOOL read_node_cfg(scfg_t* cfg, char* error)
get_int(cfg->sec_hangup,instream);
if(!cfg->sec_hangup)
cfg->sec_hangup=300;
for(i=0;i<188;i++) { /* Unused - initialized to NULL */
fread(&n,1,2,instream);
offset+=2; }
for(i=0;i<256;i++) { /* Unused - initialized to 0xff */
fread(&n,1,2,instream);
offset+=2; }
/***************/
/* Modem Stuff */
/***************/
get_int(cfg->com_port,instream);
get_int(cfg->com_irq,instream);
get_int(cfg->com_base,instream);
get_int(cfg->com_rate,instream);
get_int(cfg->mdm_misc,instream);
get_str(cfg->mdm_init,instream);
get_str(cfg->mdm_spec,instream);
get_str(cfg->mdm_term,instream);
get_str(cfg->mdm_dial,instream);
get_str(cfg->mdm_offh,instream);
get_str(cfg->mdm_answ,instream);
get_int(cfg->mdm_reinit,instream);
get_int(cfg->mdm_ansdelay,instream);
get_int(cfg->mdm_rings,instream);
get_int(cfg->mdm_results,instream);
if(cfg->mdm_results) {
if((cfg->mdm_result=(mdm_result_t *)malloc(sizeof(mdm_result_t)*cfg->mdm_results))
==NULL)
return allocerr(instream,error,offset,fname,sizeof(mdm_result_t *)*cfg->mdm_results);
} else
cfg->mdm_result=NULL;
get_int(cfg->node_erruser, instream);
get_int(cfg->node_errlevel, instream);
for(i=0;i<cfg->mdm_results;i++) {
if(feof(instream)) break;
get_int(cfg->mdm_result[i].code,instream);
get_int(cfg->mdm_result[i].rate,instream);
get_int(cfg->mdm_result[i].cps,instream);
get_str(cfg->mdm_result[i].str,instream);
}
cfg->mdm_results=i;
fclose(instream);
return(TRUE);
}
......
......@@ -82,7 +82,6 @@ BOOL DLLCALL write_node_cfg(scfg_t* cfg, int backup_level)
{
char str[MAX_PATH+1];
int i,file;
uint16_t n;
FILE *stream;
if(cfg->prepped)
......@@ -136,33 +135,8 @@ BOOL DLLCALL write_node_cfg(scfg_t* cfg, int backup_level)
put_str(cfg->scfg_cmd,stream);
put_int(cfg->sec_warn,stream);
put_int(cfg->sec_hangup,stream);
n=0;
for(i=0;i<188;i++) /* unused init to NULL */
fwrite(&n,1,2,stream);
n=0xffff; /* unused init to 0xff */
for(i=0;i<256;i++)
fwrite(&n,1,2,stream);
put_int(cfg->com_port,stream);
put_int(cfg->com_irq,stream);
put_int(cfg->com_base,stream);
put_int(cfg->com_rate,stream);
put_int(cfg->mdm_misc,stream);
put_str(cfg->mdm_init,stream);
put_str(cfg->mdm_spec,stream);
put_str(cfg->mdm_term,stream);
put_str(cfg->mdm_dial,stream);
put_str(cfg->mdm_offh,stream);
put_str(cfg->mdm_answ,stream);
put_int(cfg->mdm_reinit,stream);
put_int(cfg->mdm_ansdelay,stream);
put_int(cfg->mdm_rings,stream);
put_int(cfg->mdm_results,stream);
for(i=0;i<cfg->mdm_results;i++) {
put_int(cfg->mdm_result[i].code,stream);
put_int(cfg->mdm_result[i].rate,stream);
put_int(cfg->mdm_result[i].cps,stream);
put_str(cfg->mdm_result[i].str,stream);
}
put_int(cfg->node_erruser,stream);
put_int(cfg->node_errlevel,stream);
fclose(stream);
return(TRUE);
......
......@@ -139,7 +139,7 @@ static int lprintf(int level, const char *fmt, ...)
if(level <= LOG_ERR) {
char errmsg[sizeof(sbuf)+16];
SAFEPRINTF(errmsg, "srvc %s", sbuf);
errorlog(&scfg,startup==NULL ? NULL:startup->host_name, errmsg);
errorlog(&scfg, level, startup==NULL ? NULL:startup->host_name, errmsg);
if(startup!=NULL && startup->errormsg!=NULL)
startup->errormsg(startup->cbdata,level,errmsg);
}
......@@ -2037,7 +2037,7 @@ void DLLCALL services_thread(void* arg)
,&client_addr.addr, &client_addr_len);
if(udp_len<1) {
FREE_AND_NULL(udp_buf);
lprintf(LOG_ERR,"%04d %s !ERROR %d (%s) recvfrom failed"
lprintf(LOG_WARNING,"%04d %s !ERROR %d (%s) recvfrom failed"
,service[i].set->socks[j].sock, service[i].protocol, ERROR_VALUE, socket_strerror(socket_errno));
continue;
}
......
......@@ -556,7 +556,7 @@ static int lprintf(int level, const char *fmt, ...)
if(level <= LOG_ERR) {
char errmsg[sizeof(sbuf)+16];
SAFEPRINTF(errmsg, "web %s", sbuf);
errorlog(&scfg,startup==NULL ? NULL:startup->host_name, errmsg);
errorlog(&scfg, level, startup==NULL ? NULL:startup->host_name, errmsg);
if(startup!=NULL && startup->errormsg!=NULL)
startup->errormsg(startup->cbdata,level,errmsg);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment