summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2001-11-01 15:38:49 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2001-11-01 15:38:49 +0000
commit65e690315175530ba12d03b614f6354fea27335d (patch)
treee6d76734dff2e385022ac0916b0e5c78210ec8ac
parent038ae3432fc51991a9164cc02dbce6cc0a859351 (diff)
downloadmailutils-65e690315175530ba12d03b614f6354fea27335d.tar.gz
mailutils-65e690315175530ba12d03b614f6354fea27335d.tar.bz2
Configuration and ACL routines.
-rw-r--r--comsat/cfg.c295
1 files changed, 295 insertions, 0 deletions
diff --git a/comsat/cfg.c b/comsat/cfg.c
new file mode 100644
index 000000000..a1a7a9bd4
--- /dev/null
+++ b/comsat/cfg.c
@@ -0,0 +1,295 @@
+/* Copyright (C) 1998,2001 Free Software Foundation, Inc.
+
+ This file is part of GNU Inetutils.
+
+ GNU Inetutils 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.
+
+ GNU Inetutils is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR 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 GNU Inetutils; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "comsat.h"
+#include <argcv.h>
+#include <ctype.h>
+
+typedef struct netdef netdef_t;
+
+struct netdef
+{
+ netdef_t *next;
+ unsigned int ipaddr;
+ unsigned int netmask;
+};
+
+#define ACT_ALLOW 0
+#define ACT_DENY 1
+
+typedef struct acl acl_t;
+
+struct acl
+{
+ acl_t *next;
+ netdef_t *netlist;
+ int action;
+};
+
+
+acl_t *acl_head, *acl_tail;
+
+#define DOTTED_QUAD_LEN 16
+
+static int
+read_address (char **line_ptr, char *ptr)
+{
+ char *startp = *line_ptr;
+ char *endp;
+ int dotcount = 0;
+
+ for (endp = startp; *endp; endp++, ptr++)
+ if (!(isdigit (*endp) || *endp == '.'))
+ break;
+ else if (endp < startp + DOTTED_QUAD_LEN)
+ {
+ if (*endp == '.')
+ dotcount++;
+ *ptr = *endp;
+ }
+ else
+ break;
+ *line_ptr = endp;
+ *ptr = 0;
+ return dotcount;
+}
+
+static netdef_t *
+netdef_parse (char *str)
+{
+ unsigned int ipaddr, netmask;
+ netdef_t *netdef;
+ char ipbuf[DOTTED_QUAD_LEN+1];
+
+ if (strcmp (str, "any") == 0)
+ {
+ ipaddr = 0;
+ netmask = 0;
+ }
+ else
+ {
+ read_address (&str, ipbuf);
+ ipaddr = inet_addr (ipbuf);
+ if (ipaddr == INADDR_NONE)
+ return NULL;
+ if (*str == 0)
+ netmask = 0xfffffffful;
+ else if (*str != '/')
+ return NULL;
+ else
+ {
+ str++;
+ if (read_address (&str, ipbuf) == 0)
+ {
+ /* netmask length */
+ unsigned int len = strtoul (ipbuf, NULL, 0);
+ if (len > 32)
+ return NULL;
+ netmask = 0xfffffffful >> (32-len);
+ netmask <<= (32-len);
+ /*FIXME: hostorder?*/
+ }
+ else
+ netmask = inet_network (ipbuf);
+ netmask = htonl (netmask);
+ }
+ }
+
+ netdef = malloc (sizeof *netdef);
+ if (!netdef)
+ {
+ syslog (LOG_ERR, "out of memory");
+ exit (1);
+ }
+
+ netdef->next = NULL;
+ netdef->ipaddr = ipaddr;
+ netdef->netmask = netmask;
+
+ return netdef;
+}
+
+void
+read_config (char *config_file)
+{
+ FILE *fp;
+ int line;
+ char buf[128];
+ char *ptr;
+
+ if (!config_file)
+ return;
+
+ fp = fopen (config_file, "r");
+ if (!fp)
+ {
+ syslog (LOG_ERR, "can't open config file %s: %m", config_file);
+ return;
+ }
+
+ line = 0;
+ while ((ptr = fgets (buf, sizeof buf, fp)))
+ {
+ int len, i;
+ int argc;
+ char **argv;
+ int action;
+ netdef_t *head, *tail;
+ acl_t *acl;
+
+ line++;
+ len = strlen (ptr);
+ if (len > 0 && ptr[len-1] == '\n')
+ ptr[--len] = 0;
+
+ while (*ptr && isspace (*ptr))
+ ptr++;
+ if (!*ptr || *ptr == '#')
+ continue;
+
+ argcv_get (ptr, "", &argc, &argv);
+ if (argc < 2)
+ {
+ syslog (LOG_ERR, "%s:%d: too few fields", config_file, line);
+ argcv_free (argc, argv);
+ continue;
+ }
+
+ if (strcmp (argv[0], "max-requests") == 0)
+ maxrequests = strtoul (argv[1], NULL, 0);
+ else if (strcmp (argv[0], "request-control-interval") == 0)
+ request_control_interval = strtoul (argv[1], NULL, 0);
+ else if (strcmp (argv[0], "overflow-control-interval") == 0)
+ overflow_control_interval = strtoul (argv[1], NULL, 0);
+ else if (strcmp (argv[0], "overflow-delay-time") == 0)
+ overflow_delay_time = strtoul (argv[1], NULL, 0);
+ else if (strcmp (argv[0], "max-lines") == 0)
+ maxlines = strtoul (argv[1], NULL, 0);
+ else if (strcmp (argv[0], "acl") == 0)
+ {
+ if (strcmp (argv[1], "allow") == 0)
+ action = ACT_ALLOW;
+ else if (strcmp (argv[1], "deny") == 0)
+ action = ACT_DENY;
+ else
+ {
+ syslog (LOG_ERR, "%s:%d: unknown keyword", config_file, line);
+ argcv_free (argc, argv);
+ continue;
+ }
+
+ head = tail = NULL;
+ for (i = 2; i < argc; i++)
+ {
+ netdef_t *cur = netdef_parse (argv[i]);
+ if (!cur)
+ {
+ syslog (LOG_ERR, "%s:%d: can't parse netdef: %s",
+ config_file, line, argv[i]);
+ continue;
+ }
+ if (!tail)
+ head = cur;
+ else
+ tail->next = cur;
+ tail = cur;
+ }
+
+ argcv_free (argc, argv);
+
+ acl = malloc (sizeof *acl);
+ if (!acl)
+ {
+ syslog (LOG_CRIT, "out of memory");
+ exit (1);
+ }
+ acl->next = NULL;
+ acl->action = action;
+ acl->netlist = head;
+
+ if (!acl_tail)
+ acl_head = acl;
+ else
+ acl_tail->next = acl;
+ acl_tail = acl;
+ }
+ }
+ fclose (fp);
+}
+
+static void
+netdef_free (netdef_t *netdef)
+{
+ netdef_t *next;
+
+ while (netdef)
+ {
+ next = netdef->next;
+ free (netdef);
+ netdef = next;
+ }
+}
+
+static void
+acl_free (acl_t *acl)
+{
+ acl_t *next;
+
+ while (acl)
+ {
+ next = acl->next;
+ netdef_free (acl->netlist);
+ free (acl);
+ acl = next;
+ }
+}
+
+/*NOTE: currently unused. */
+void
+discard_acl (acl_t *mark)
+{
+ if (mark)
+ {
+ acl_free (mark->next);
+ acl_tail = mark;
+ acl_tail->next = NULL;
+ }
+ else
+ acl_head = acl_tail = NULL;
+}
+
+int
+acl_match (struct sockaddr_in *sa_in)
+{
+ acl_t *acl;
+ unsigned int ip;
+
+ ip = sa_in->sin_addr.s_addr;
+ for (acl = acl_head; acl; acl = acl->next)
+ {
+ netdef_t *net;
+
+ for (net = acl->netlist; net; net = net->next)
+ {
+ if (net->ipaddr == (ip & net->netmask))
+ return acl->action;
+ }
+ }
+ return ACT_ALLOW;
+}

Return to:

Send suggestions and report system problems to the System administrator.