/***************************************************************************** * * $Id$ * Purpose ...............: Routing Setup * ***************************************************************************** * Copyright (C) 1997-2002 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 * 1971 BV IJmuiden * the Netherlands * * This file is part of MBSE BBS. * * This BBS is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * MB BBS is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MB BBS; see the file COPYING. If not, write to the Free * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. *****************************************************************************/ #include "../config.h" #include "../lib/libs.h" #include "../lib/memwatch.h" #include "../lib/structs.h" #include "../lib/users.h" #include "../lib/records.h" #include "../lib/common.h" #include "../lib/clcomm.h" #include "screen.h" #include "mutil.h" #include "ledit.h" #include "stlist.h" #include "m_global.h" #include "grlist.h" #include "m_node.h" #include "m_route.h" int RouteUpdated = 0; /* * Count nr of route records in the database. * Creates the database if it doesn't exist. */ int CountRoute(void) { FILE *fil; char *ffile; int count; ffile = calloc(PATH_MAX, sizeof(char)); sprintf(ffile, "%s/etc/route.data", getenv("MBSE_ROOT")); if ((fil = fopen(ffile, "r")) == NULL) { if ((fil = fopen(ffile, "a+")) != NULL) { Syslog('+', "Created new %s", ffile); routehdr.hdrsize = sizeof(routehdr); routehdr.recsize = sizeof(route); fwrite(&routehdr, sizeof(routehdr), 1, fil); fclose(fil); chmod(ffile, 0640); free(ffile); return 0; } else { free(ffile); return -1; } } fread(&routehdr, sizeof(routehdr), 1, fil); fseek(fil, 0, SEEK_END); count = (ftell(fil) - routehdr.hdrsize) / routehdr.recsize; fclose(fil); free(ffile); return count; } /* * Open database for editing. The datafile is copied, if the format * is changed it will be converted on the fly. All editing must be * done on the copied file. */ int OpenRoute(void) { FILE *fin, *fout; char *fnin, *fnout; long oldsize; fnin = calloc(PATH_MAX, sizeof(char)); fnout = calloc(PATH_MAX, sizeof(char)); sprintf(fnin, "%s/etc/route.data", getenv("MBSE_ROOT")); sprintf(fnout, "%s/etc/route.temp", getenv("MBSE_ROOT")); if ((fin = fopen(fnin, "r")) != NULL) { if ((fout = fopen(fnout, "w")) != NULL) { fread(&routehdr, sizeof(routehdr), 1, fin); /* * In case we are automatic upgrading the data format * we save the old format. If it is changed, the * database must always be updated. */ oldsize = routehdr.recsize; if (oldsize != sizeof(route)) { Syslog('+', "Updated %s, format changed", fnin); RouteUpdated = 1; } else RouteUpdated = 0; routehdr.hdrsize = sizeof(routehdr); routehdr.recsize = sizeof(route); fwrite(&routehdr, sizeof(routehdr), 1, fout); /* * The datarecord is filled with zero's before each * read, so if the format changed, the new fields * will be empty. */ memset(&route, 0, sizeof(route)); while (fread(&route, oldsize, 1, fin) == 1) { fwrite(&route, sizeof(route), 1, fout); memset(&route, 0, sizeof(route)); } fclose(fin); fclose(fout); free(fnin); free(fnout); return 0; } else return -1; } return -1; } /* * Update route database and sort it. Sorting is important * because the routelist is processed top-down, the first * match counts. */ void CloseRoute(int force) { char *fin, *fout; FILE *fi, *fo; st_list *new = NULL, *tmp; fin = calloc(PATH_MAX, sizeof(char)); fout = calloc(PATH_MAX, sizeof(char)); sprintf(fin, "%s/etc/route.data", getenv("MBSE_ROOT")); sprintf(fout,"%s/etc/route.temp", getenv("MBSE_ROOT")); if (RouteUpdated == 1) { if (force || (yes_no((char *)"Database is changed, save changes") == 1)) { working(1, 0, 0); fi = fopen(fout, "r"); fo = fopen(fin, "w"); fread(&routehdr, routehdr.hdrsize, 1, fi); fwrite(&routehdr, routehdr.hdrsize, 1, fo); while (fread(&route, routehdr.recsize, 1, fi) == 1) { if (!route.Deleted) { fill_stlist(&new, route.mask, ftell(fi) - routehdr.recsize); } } sort_stlist(&new); for (tmp = new; tmp; tmp = tmp->next) { fseek(fi, tmp->pos, SEEK_SET); fread(&route, routehdr.recsize, 1, fi); fwrite(&route, routehdr.recsize, 1, fo); } fclose(fi); fclose(fo); tidy_stlist(&new); unlink(fout); chmod(fin, 0640); Syslog('+', "Updated \"route.data\""); free(fin); free(fout); return; } } chmod(fin, 0640); working(1, 0, 0); unlink(fout); free(fin); free(fout); } int AppendRoute(void) { FILE *fil; char *ffile; ffile = calloc(PATH_MAX, sizeof(char)); sprintf(ffile, "%s/etc/route.temp", getenv("MBSE_ROOT")); if ((fil = fopen(ffile, "a")) != NULL) { memset(&route, 0, sizeof(route)); /* * Fill in default values */ route.routetype = R_NOROUTE; fwrite(&route, sizeof(route), 1, fil); fclose(fil); RouteUpdated = 1; free(ffile); return 0; } free(ffile); return -1; } #define RCHARS "All:/.0123456789" /* * Check syntax of entered routing mask. */ int RouteSyntax(char *); int RouteSyntax(char *s) { char *str, *p; if (strspn(s, RCHARS) != strlen(s)) return FALSE; str = xstrcpy(s); if ((p = strchr(str, ':'))) { *(p++) = '\0'; if (strspn(str, "0123456789") != strlen(str)) { if (strcmp(str, "All")) return FALSE; } else if (strlen(p) == 0) return FALSE; str = p; } else { if (strcmp(str, "All")) return FALSE; } if ((p = strchr(str, '/'))) { *(p++) = '\0'; if (strspn(str, "0123456789") != strlen(str)) { if (strcmp(str, "All")) return FALSE; } else if (strlen(p) == 0) return FALSE; str = p; } else { if (strcmp(str, "All")) return FALSE; } if ((p = strchr(str, '.'))) { *(p++) = '\0'; if (strspn(str, "0123456789") != strlen(str)) { if (strcmp(str, "All")) return FALSE; } if (strlen(p) == 0) return FALSE; str = p; } else { if (strspn(str, "0123456789") != strlen(str)) { if (strcmp(str, "All")) return FALSE; } str = NULL; } return TRUE; } void RouteScreen(void) { clr_index(); set_color(WHITE, BLACK); mvprintw( 5, 5, "19. EDIT ROUTING TABLE"); set_color(CYAN, BLACK); mvprintw( 7, 5, "1. Mask"); // mvprintw( 8, 5, "2. Src name"); mvprintw( 9, 5, "3. Action"); mvprintw(10, 5, "4. Dest addr"); // mvprintw(11, 5, "5. Dest name"); mvprintw(12, 5, "6. Active"); mvprintw(13, 5, "7. Deleted"); } /* * Edit one record, return -1 if record doesn't exist, 0 if ok. */ int EditRouteRec(int Area) { FILE *fil; char *mfile, newmask[25]; long offset; unsigned long crc, crc1; int i; clr_index(); working(1, 0, 0); IsDoing("Edit Route"); mfile = calloc(PATH_MAX, sizeof(char)); sprintf(mfile, "%s/etc/route.temp", getenv("MBSE_ROOT")); if ((fil = fopen(mfile, "r")) == NULL) { working(2, 0, 0); free(mfile); return -1; } fread(&routehdr, sizeof(routehdr), 1, fil); offset = routehdr.hdrsize + ((Area -1) * routehdr.recsize); if (fseek(fil, offset, 0) != 0) { working(2, 0, 0); free(mfile); return -1; } fread(&route, routehdr.recsize, 1, fil); fclose(fil); crc = 0xffffffff; crc = upd_crc32((char *)&route, crc, routehdr.recsize); working(0, 0, 0); RouteScreen(); for (;;) { set_color(WHITE, BLACK); show_str( 7,20,24, route.mask); show_str( 8,20,36, route.sname); show_routetype(9,20, route.routetype); show_str( 10,20,35, aka2str(route.dest)); show_str( 11,20,35, route.dname); show_bool(12,20, route.Active); show_bool(13,20, route.Deleted); switch(select_menu(7)) { case 0: crc1 = 0xffffffff; crc1 = upd_crc32((char *)&route, crc1, routehdr.recsize); if (crc != crc1) { if (yes_no((char *)"Record is changed, save") == 1) { working(1, 0, 0); if ((fil = fopen(mfile, "r+")) == NULL) { working(2, 0, 0); free(mfile); return -1; } fseek(fil, offset, 0); fwrite(&route, routehdr.recsize, 1, fil); fclose(fil); RouteUpdated = 1; working(0, 0, 0); } } free(mfile); IsDoing("Browsing Menu"); return 0; case 1: strcpy(newmask, edit_str( 7,20,24, route.mask, (char *)"The ^routing mask^ to match, ie: ^1:All^, ^2:280/All^, ^2:280/28^")); /* * First make all chars in the right case, the only allowed word is "All". */ for (i = 0; i < strlen(newmask); i++) { if (newmask[i] == 'a') newmask[i] = 'A'; if (newmask[i] == 'L') newmask[i] = 'l'; } if (RouteSyntax(newmask)) { if (strlen(newmask) && !strlen(route.mask)) route.Active = TRUE; strcpy(route.mask, newmask); } else errmsg("Syntax error"); break; // case 2: E_STR( 8,20,36, route.sname, "The additional ^source username^ to add to the match"); case 3: route.routetype = edit_routetype(9,20, route.routetype); break; case 4: route.dest = PullUplink((char *)"19.4"); RouteScreen(); break; // case 5: E_STR( 11,20,36, route.dname, "The ^destination name^ if needed"); case 6: E_BOOL(12,20, route.Active, "If this route is ^active^"); case 7: E_BOOL(13,20, route.Deleted, "If this route must be ^deleted^"); } } } void EditRoute(void) { int records, i, o, x, y; char pick[12], *temp; FILE *fil; long offset; clr_index(); working(1, 0, 0); IsDoing("Browsing Menu"); if (config_read() == -1) { working(2, 0, 0); return; } records = CountRoute(); if (records == -1) { working(2, 0, 0); return; } if (OpenRoute() == -1) { working(2, 0, 0); return; } working(0, 0, 0); o = 0; temp = calloc(PATH_MAX, sizeof(char)); for (;;) { clr_index(); set_color(WHITE, BLACK); mvprintw( 5, 4, "19. ROUTING TABLE"); set_color(CYAN, BLACK); if (records != 0) { sprintf(temp, "%s/etc/route.temp", getenv("MBSE_ROOT")); working(1, 0, 0); if ((fil = fopen(temp, "r")) != NULL) { fread(&routehdr, sizeof(routehdr), 1, fil); x = 2; y = 7; set_color(CYAN, BLACK); for (i = 1; i <= 10; i++) { if ((o + i) <= records) { offset = sizeof(routehdr) + (((o + i) - 1) * routehdr.recsize); fseek(fil, offset, 0); fread(&route, routehdr.recsize, 1, fil); if (route.Deleted) set_color(LIGHTRED, BLACK); else if (route.Active) set_color(CYAN, BLACK); else set_color(LIGHTBLUE, BLACK); sprintf(temp, "%3d. %-25s %s %s", o + i, route.mask, get_routetype(route.routetype), aka2str(route.dest)); // temp[37] = 0; mvprintw(y, x, temp); y++; } } fclose(fil); } } working(0, 0, 0); strcpy(pick, select_record(records, 10)); if (strncmp(pick, "-", 1) == 0) { CloseRoute(FALSE); free(temp); return; } if (strncmp(pick, "A", 1) == 0) { working(1, 0, 0); if (AppendRoute() == 0) { records++; working(1, 0, 0); } else working(2, 0, 0); working(0, 0, 0); } if (strncmp(pick, "N", 1) == 0) if ((o + 10) < records) o = o + 10; if (strncmp(pick, "P", 1) == 0) if ((o - 10) >= 0) o = o - 10; if ((atoi(pick) >= 1) && (atoi(pick) <= records)) { EditRouteRec(atoi(pick)); o = ((atoi(pick) - 1) / 10) * 10; } } } void InitRoute(void) { CountRoute(); OpenRoute(); CloseRoute(TRUE); } int route_doc(FILE *fp, FILE *toc, int page) { char *temp; FILE *no; int j; temp = calloc(PATH_MAX, sizeof(char)); sprintf(temp, "%s/etc/route.data", getenv("MBSE_ROOT")); if ((no = fopen(temp, "r")) == NULL) { free(temp); return page; } page = newpage(fp, page); addtoc(fp, toc, 12, 0, page, (char *)"Routing table"); j = 0; fprintf(fp, "\n\n"); fread(&routehdr, sizeof(routehdr), 1, no); while ((fread(&route, routehdr.recsize, 1, no)) == 1) { if (j == 5) { page = newpage(fp, page); fprintf(fp, "\n"); j = 0; } fprintf(fp, " Route mask %s\n", route.mask); fprintf(fp, " Src username %s\n", route.sname); fprintf(fp, " Route action %s\n", get_routetype(route.routetype)); fprintf(fp, " Destination %s\n", aka2str(route.dest)); fprintf(fp, " Dest username %s\n", route.dname); fprintf(fp, " Active %s\n", getboolean(route.Active)); fprintf(fp, "\n\n"); j++; } fclose(no); free(temp); return page; }