]> code.citadel.org Git - citadel.git/blobdiff - citadel/netproc.c
* Replication fixes
[citadel.git] / citadel / netproc.c
index c362cf238f54272d2fec2be80cdf3a5cf6e440d3..9a531dea537a8d82e18fbdbf2bf19d4f70e3129a 100644 (file)
 /* Path to the 'uudecode' utility (needed for network file transfers) */
 #define UUDECODE       "/usr/bin/uudecode"
 
+/* Files used by the networker */
+#define MAILSYSINFO    "./network/mail.sysinfo"
+
 /* Uncomment the DEBUG def to see noisy traces */
-/* #define DEBUG 1 */
+#define DEBUG 1
 
 
 #include "sysdep.h"
@@ -92,6 +95,8 @@ struct config config;
 extern char bbs_home_directory[];
 extern int home_specified;
 
+GDBM_FILE use_table;
+
 
 #ifndef HAVE_STRERROR
 /*
@@ -115,7 +120,7 @@ void strip_trailing_whitespace(char *buf)
 
 
 /*
- * we also load the network/mail.sysinfo table into memory, make changes
+ * we also load the mail.sysinfo table into memory, make changes
  * as we learn more about the network from incoming messages, and write
  * the table back to disk when we're done.
  */
@@ -126,7 +131,7 @@ int load_syslist(void)
        char insys = 0;
        char buf[128];
 
-       fp = fopen("network/mail.sysinfo", "r");
+       fp = fopen(MAILSYSINFO, "r");
        if (fp == NULL)
                return (1);
 
@@ -231,7 +236,7 @@ void rewrite_syslist(void)
        time_t now;
 
        time(&now);
-       newfp = fopen("network/mail.sysinfo", "w");
+       newfp = fopen(MAILSYSINFO, "w");
        for (stemp = slist; stemp != NULL; stemp = stemp->next) {
                if (!strcasecmp(stemp->s_name, config.c_nodename)) {
                        time(&stemp->s_lastcontact);
@@ -307,6 +312,11 @@ int set_lockfile(void)
                        return 1;
        }
        lfp = fopen(LOCKFILE, "w");
+       if (lfp == NULL) {
+               syslog(LOG_NOTICE, "Cannot create %s: %s", LOCKFILE,
+                       strerror(errno));
+               return(1);
+       }
        fprintf(lfp, "%ld\n", (long) getpid());
        fclose(lfp);
        return (0);
@@ -463,33 +473,22 @@ void fpgetfield(FILE * fp, char *string)
  * Load all of the fields of a message, except the actual text, into a
  * table in memory (so we know how to process the message).
  */
-void msgfind(char *msgfile, struct minfo *buffer)
+void fpmsgfind(FILE *fp, struct minfo *buffer)
 {
        int b, e, mtype, aflag;
        char bbb[1024];
        char userid[1024];
-       FILE *fp;
 
        strcpy(userid, "");
-       fp = fopen(msgfile, "rb");
-       if (fp == NULL) {
-               syslog(LOG_ERR, "can't open message file: %s", strerror(errno));
-               return;
-       }
        e = getc(fp);
        if (e != 255) {
-               syslog(LOG_ERR, "incorrect message format");
+               syslog(LOG_ERR, "Magic number check failed for this message");
                goto END;
        }
+
+       memset(buffer, 0, sizeof(struct minfo));
        mtype = getc(fp);
        aflag = getc(fp);
-       buffer->I = 0L;
-       buffer->R[0] = 0;
-       buffer->E[0] = 0;
-       buffer->H[0] = 0;
-       buffer->S[0] = 0;
-       buffer->B[0] = 0;
-       buffer->G[0] = 0;
 
 BONFGM:        b = getc(fp);
        if (b < 0)
@@ -548,9 +547,11 @@ BONFGM:    b = getc(fp);
                strcpy(buffer->G, bbb);
        if (b == 'E')
                strcpy(buffer->E, bbb);
+       if (b == 'Z')
+               strcpy(buffer->Z, bbb);
        goto BONFGM;
 
-END:   fclose(fp);
+END:
 
        /* NOTE: we used to use the following two lines of code to assign
         * the timestamp as a message-ID if there was no message-ID already
@@ -563,6 +564,24 @@ END:       fclose(fp);
 }
 
 
+/*
+ * msgfind() is the same as fpmsgfind() except it accepts a filename
+ * instead of a file handle.
+ */
+void msgfind(char *msgfile, struct minfo *buffer) {
+       FILE *fp;
+
+       fp = fopen(msgfile, "rb");
+       if (fp == NULL) {
+               syslog(LOG_ERR, "can't open %s: %s", msgfile, strerror(errno));
+               return;
+       }
+
+       fpmsgfind(fp, buffer);
+       fclose(fp);
+}
+
+
 
 
 
@@ -796,6 +815,8 @@ void purge_use_table(GDBM_FILE ut) {
 
 
 
+
+
 /*
  * process incoming files in ./network/spoolin
  */
@@ -812,7 +833,6 @@ void inprocess(void)
        char buf[256];
        long msglen;
        int bloklen;
-       GDBM_FILE use_table;
 
        /* temp file names */
        sprintf(tname, tmpnam(NULL));
@@ -823,15 +843,6 @@ void inprocess(void)
        /* Make sure we're in the right directory */
        chdir(bbs_home_directory);
 
-       /* Open the use table */
-       use_table = gdbm_open("./data/usetable.gdbm", 512,
-                             GDBM_WRCREAT, 0600, 0);
-       if (use_table == NULL) {
-               syslog(LOG_ERR, "could not open use table: %s",
-                      strerror(errno));
-       }
-
-
        /* temporary file to contain a log of rejected dups */
        duplist = tmpfile();
 
@@ -846,6 +857,10 @@ void inprocess(void)
                        do {
 SKIP:                          ptr = fgets(sfilename, sizeof sfilename, ls);
                                if (ptr != NULL) {
+#ifdef DEBUG
+                                       syslog(LOG_DEBUG,
+                                               "Trying %s", sfilename);
+#endif
                                        sfilename[strlen(sfilename) - 1] = 0;
                                        if (!strcmp(sfilename, ".")) goto SKIP;
                                        if (!strcmp(sfilename, "..")) goto SKIP;
@@ -897,11 +912,6 @@ NXMSG:     /* Seek to the beginning of the next message */
                        fclose(message);
 
                        /* process the individual mesage */
-                       minfo.D[0] = 0;
-                       minfo.C[0] = 0;
-                       minfo.B[0] = 0;
-                       minfo.G[0] = 0;
-                       minfo.R[0] = 0;
                        msgfind(tname, &minfo);
                        strncpy(recentmsg.RMnodename, minfo.N, 9);
                        recentmsg.RMnodename[9] = 0;
@@ -998,7 +1008,6 @@ NXMSG:     /* Seek to the beginning of the next message */
 
                        /* otherwise process it as a normal message */
                        else {
-
                                if (!strcasecmp(minfo.R, "postmaster")) {
                                        strcpy(minfo.R, "");
                                        strcpy(minfo.C, "Aide");
@@ -1060,6 +1069,7 @@ NXMSG:    /* Seek to the beginning of the next message */
                                }
 
                                fclose(message);
+                               
                        }
 
                        unlink(tname);
@@ -1071,9 +1081,6 @@ ENDSTR:                   fclose(fp);
        } while (ptr != NULL);
        unlink(iname);
 
-       purge_use_table(use_table);
-       gdbm_close(use_table);
-
 
        /*
         * If dups were rejected, post a message saying so
@@ -1123,15 +1130,17 @@ int checkpath(char *path, char *sys)
 }
 
 /*
- * implement split horizon algorithm
+ * Implement split horizon algorithm (prevent infinite spooling loops
+ * by refusing to send any node a message which already contains its
+ * nodename in the path).
  */
-int ismsgok(long int mpos, FILE * mmfp, char *sysname)
+int ismsgok(FILE *mmfp, char *sysname)
 {
        int a;
        int ok = 0;             /* fail safe - no path, don't send it */
        char fbuf[256];
 
-       fseek(mmfp, mpos, 0);
+       fseek(mmfp, 0L, 0);
        if (getc(mmfp) != 255)
                return (0);
        getc(mmfp);
@@ -1162,6 +1171,7 @@ int spool_out(struct msglist *cmlist, FILE * destfp, char *sysname)
        int msgs_spooled = 0;
        long msg_len;
        int blok_len;
+       static struct minfo minfo;
 
        char buf[256];
        char curr_rm[256];
@@ -1201,7 +1211,7 @@ int spool_out(struct msglist *cmlist, FILE * destfp, char *sysname)
 
                rewind(mmfp);
 
-               if (ismsgok(0L, mmfp, sysname)) {
+               if (ismsgok(mmfp, sysname)) {
                        ++msgs_spooled;
                        fflush(stdout);
                        fseek(mmfp, 0L, 0);
@@ -1225,6 +1235,14 @@ int spool_out(struct msglist *cmlist, FILE * destfp, char *sysname)
                                        putc(a, destfp);
                                } while (a > 0);
                        }
+
+               /* Get this message into the use table, so we can reject it
+                * if a misconfigured remote system sends it back to us.
+                */
+               fseek(mmfp, 0L, 0);
+               fpmsgfind(mmfp, &minfo);
+               already_received(use_table, &minfo);
+
                }
                fclose(mmfp);
        }
@@ -1437,8 +1455,14 @@ int main(int argc, char **argv)
                }
        }
 
+#ifdef DEBUG
+       syslog(LOG_DEBUG, "Calling get_config()");
+#endif
        get_config();
 
+#ifdef DEBUG
+       syslog(LOG_DEBUG, "Creating lock file");
+#endif
        if (set_lockfile() != 0) {
                syslog(LOG_NOTICE, "lock file exists: already running");
                cleanup(1);
@@ -1457,8 +1481,21 @@ int main(int argc, char **argv)
                syslog(LOG_ERR, "cannot load sysinfo");
        setup_special_nodes();
 
-       inprocess();            /* first collect incoming stuff */
+       /* Open the use table */
+       use_table = gdbm_open("./data/usetable.gdbm", 512,
+                             GDBM_WRCREAT, 0600, 0);
+       if (use_table == NULL) {
+               syslog(LOG_ERR, "could not open use table: %s",
+                      strerror(errno));
+       }
 
+       /* first collect incoming stuff */
+       inprocess();
+
+       /* Now process outbound messages, but NOT if this is just a
+        * quick import-only run (i.e. the -i command-line option
+        * was specified)
+        */
        if (import_only != 1) {
                allfp = (FILE *) popen("cd ./network/systems; ls", "r");
                if (allfp != NULL) {
@@ -1471,7 +1508,14 @@ int main(int argc, char **argv)
                /* import again in case anything new was generated */
                inprocess();
        }
+
+       /* Update mail.sysinfo with new information we learned */
        rewrite_syslist();
+
+       /* Close the use table */
+       purge_use_table(use_table);
+       gdbm_close(use_table);
+
        syslog(LOG_NOTICE, "processing ended.");
        cleanup(0);
        return 0;