summaryrefslogtreecommitdiff
path: root/src/pluto/foodgroups.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pluto/foodgroups.c')
-rw-r--r--src/pluto/foodgroups.c450
1 files changed, 0 insertions, 450 deletions
diff --git a/src/pluto/foodgroups.c b/src/pluto/foodgroups.c
deleted file mode 100644
index e4f9a1d01..000000000
--- a/src/pluto/foodgroups.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/* Implement policy groups-style control files (aka "foodgroups")
- * Copyright (C) 2002 D. Hugh Redelmeier.
- *
- * This program 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 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program 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.
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <sys/queue.h>
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "connections.h"
-#include "foodgroups.h"
-#include "kernel.h"
-#include "lex.h"
-#include "log.h"
-#include "whack.h"
-
-
-/* Food group config files are found in directory fg_path */
-
-#ifndef POLICYGROUPSDIR
-#define POLICYGROUPSDIR IPSEC_CONFDIR "/ipsec.d/policies"
-#endif
-
-const char *policygroups_dir = POLICYGROUPSDIR;
-
-static char *fg_path = NULL;
-static size_t fg_path_space = 0;
-
-
-/* Groups is a list of connections that are policy groups.
- * The list is updated as group connections are added and deleted.
- */
-
-struct fg_groups {
- struct fg_groups *next;
- connection_t *connection;
-};
-
-static struct fg_groups *groups = NULL;
-
-
-/* Targets is a list of pairs: subnet and its policy group.
- * This list is bulk-updated on whack --listen and
- * incrementally updated when group connections are deleted.
- *
- * It is ordered by source subnet, and if those are equal, then target subnet.
- * A subnet is compared by comparing the network, and if those are equal,
- * comparing the mask.
- */
-
-struct fg_targets {
- struct fg_targets *next;
- struct fg_groups *group;
- ip_subnet subnet;
- char *name; /* name of instance of group conn */
-};
-
-static struct fg_targets *targets = NULL;
-
-struct fg_targets *new_targets;
-
-/* ipcmp compares the two ip_address values a and b.
- * It returns -1, 0, or +1 if a is, respectively,
- * less than, equal to, or greater than b.
- */
-static int ipcmp(ip_address *a, ip_address *b)
-{
- if (addrtypeof(a) != addrtypeof(b))
- {
- return addrtypeof(a) < addrtypeof(b)? -1 : 1;
- }
- else if (sameaddr(a, b))
- {
- return 0;
- }
- else
- {
- const struct sockaddr *sa = sockaddrof(a)
- , *sb = sockaddrof(b);
-
- passert(addrtypeof(a) == AF_INET); /* not yet implemented IPv6 version :-( */
- return (ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr)
- < ntohl(((const struct sockaddr_in *)sb)->sin_addr.s_addr))
- ? -1 : 1;
- }
-}
-
-/* subnetcmp compares the two ip_subnet values a and b.
- * It returns -1, 0, or +1 if a is, respectively,
- * less than, equal to, or greater than b.
- */
-static int subnetcmp(const ip_subnet *a, const ip_subnet *b)
-{
- ip_address neta, maska, netb, maskb;
- int r;
-
- networkof(a, &neta);
- maskof(a, &maska);
- networkof(b, &netb);
- maskof(b, &maskb);
- r = ipcmp(&neta, &netb);
- if (r == 0)
- r = ipcmp(&maska, &maskb);
- return r;
-}
-
-static void read_foodgroup(struct fg_groups *g)
-{
- const char *fgn = g->connection->name;
- const ip_subnet *lsn = &g->connection->spd.this.client;
- size_t plen = strlen(policygroups_dir) + 1 + strlen(fgn) + 1;
- struct file_lex_position flp_space;
-
- if (plen > fg_path_space)
- {
- free(fg_path);
- fg_path_space = plen + 10;
- fg_path = malloc(fg_path_space);
- }
- snprintf(fg_path, fg_path_space, "%s/%s", policygroups_dir, fgn);
- if (!lexopen(&flp_space, fg_path, TRUE))
- {
- DBG(DBG_CONTROL, DBG_log("no group file \"%s\"", fg_path));
- }
- else
- {
- plog("loading group \"%s\"", fg_path);
- for (;;)
- {
- switch (flp->bdry)
- {
- case B_none:
- {
- /* !!! this test is not sufficient for distinguishing address families.
- * We need a notation to specify that a FQDN is to be resolved to IPv6.
- */
- const struct af_info *afi = strchr(tok, ':') == NULL
- ? &af_inet4_info: &af_inet6_info;
- ip_subnet sn;
- err_t ugh;
-
- if (strchr(tok, '/') == NULL)
- {
- /* no /, so treat as /32 or V6 equivalent */
- ip_address t;
-
- ugh = ttoaddr(tok, 0, afi->af, &t);
- if (ugh == NULL)
- ugh = addrtosubnet(&t, &sn);
- }
- else
- {
- ugh = ttosubnet(tok, 0, afi->af, &sn);
- }
-
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s \"%s\""
- , flp->filename, flp->lino, ugh, tok);
- }
- else if (afi->af != AF_INET)
- {
- loglog(RC_LOG_SERIOUS
- , "\"%s\" line %d: unsupported Address Family \"%s\""
- , flp->filename, flp->lino, tok);
- }
- else
- {
- /* Find where new entry ought to go in new_targets. */
- struct fg_targets **pp;
- int r;
-
- for (pp = &new_targets; ; pp = &(*pp)->next)
- {
- if (*pp == NULL)
- {
- r = -1; /* end of list is infinite */
- break;
- }
- r = subnetcmp(lsn, &(*pp)->group->connection->spd.this.client);
- if (r == 0)
- r = subnetcmp(&sn, &(*pp)->subnet);
- if (r <= 0)
- break;
- }
-
- if (r == 0)
- {
- char source[SUBNETTOT_BUF];
-
- subnettot(lsn, 0, source, sizeof(source));
- loglog(RC_LOG_SERIOUS
- , "\"%s\" line %d: subnet \"%s\", source %s, already \"%s\""
- , flp->filename
- , flp->lino
- , tok
- , source
- , (*pp)->group->connection->name);
- }
- else
- {
- struct fg_targets *f = malloc_thing(struct fg_targets);
-
- f->next = *pp;
- f->group = g;
- f->subnet = sn;
- f->name = NULL;
- *pp = f;
- }
- }
- }
- (void)shift(); /* next */
- continue;
-
- case B_record:
- flp->bdry = B_none; /* eat the Record Boundary */
- (void)shift(); /* get real first token */
- continue;
-
- case B_file:
- break; /* done */
- }
- break; /* if we reach here, out of loop */
- }
- lexclose();
- }
-}
-
-static void free_targets(void)
-{
- while (targets != NULL)
- {
- struct fg_targets *t = targets;
-
- targets = t->next;
- free(t->name);
- free(t);
- }
-}
-
-void load_groups(void)
-{
- passert(new_targets == NULL);
-
- /* for each group, add config file targets into new_targets */
- {
- struct fg_groups *g;
-
- for (g = groups; g != NULL; g = g->next)
- if (oriented(*g->connection))
- read_foodgroup(g);
- }
-
- /* dump new_targets */
- DBG(DBG_CONTROL,
- {
- struct fg_targets *t;
-
- for (t = new_targets; t != NULL; t = t->next)
- {
- char asource[SUBNETTOT_BUF];
- char atarget[SUBNETTOT_BUF];
-
- subnettot(&t->group->connection->spd.this.client
- , 0, asource, sizeof(asource));
- subnettot(&t->subnet, 0, atarget, sizeof(atarget));
- DBG_log("%s->%s %s"
- , asource, atarget
- , t->group->connection->name);
- }
- });
-
- /* determine and deal with differences between targets and new_targets.
- * structured like a merge.
- */
- {
- struct fg_targets *op = targets
- , *np = new_targets;
-
- while (op != NULL && np != NULL)
- {
- int r = subnetcmp(&op->group->connection->spd.this.client
- , &np->group->connection->spd.this.client);
-
- if (r == 0)
- r = subnetcmp(&op->subnet, &np->subnet);
-
- if (r == 0 && op->group == np->group)
- {
- /* unchanged -- steal name & skip over */
- np->name = op->name;
- op->name = NULL;
- op = op->next;
- np = np->next;
- }
- else
- {
- /* note: following cases overlap! */
- if (r <= 0)
- {
- remove_group_instance(op->group->connection, op->name);
- op = op->next;
- }
- if (r >= 0)
- {
- np->name = add_group_instance(np->group->connection, &np->subnet);
- np = np->next;
- }
- }
- }
- for (; op != NULL; op = op->next)
- remove_group_instance(op->group->connection, op->name);
- for (; np != NULL; np = np->next)
- np->name = add_group_instance(np->group->connection, &np->subnet);
-
- /* update: new_targets replaces targets */
- free_targets();
- targets = new_targets;
- new_targets = NULL;
- }
-}
-
-
-void add_group(connection_t *c)
-{
- struct fg_groups *g = malloc_thing(struct fg_groups);
-
- g->next = groups;
- groups = g;
-
- g->connection = c;
-}
-
-static struct fg_groups *find_group(const connection_t *c)
-{
- struct fg_groups *g;
-
- for (g = groups; g != NULL && g->connection != c; g = g->next)
- ;
- return g;
-}
-
-void route_group(connection_t *c)
-{
- /* it makes no sense to route a connection that is ISAKMP-only */
- if (!NEVER_NEGOTIATE(c->policy) && !HAS_IPSEC_POLICY(c->policy))
- {
- loglog(RC_ROUTE, "cannot route an ISAKMP-only group connection");
- }
- else
- {
- struct fg_groups *g = find_group(c);
- struct fg_targets *t;
-
- passert(g != NULL);
- g->connection->policy |= POLICY_GROUTED;
- for (t = targets; t != NULL; t = t->next)
- {
- if (t->group == g)
- {
- connection_t *ci = con_by_name(t->name, FALSE);
-
- if (ci != NULL)
- {
- set_cur_connection(ci);
- if (!trap_connection(ci))
- whack_log(RC_ROUTE, "could not route");
- set_cur_connection(c);
- }
- }
- }
- }
-}
-
-void unroute_group(connection_t *c)
-{
- struct fg_groups *g = find_group(c);
- struct fg_targets *t;
-
- passert(g != NULL);
- g->connection->policy &= ~POLICY_GROUTED;
- for (t = targets; t != NULL; t = t->next)
- {
- if (t->group == g)
- {
- connection_t *ci = con_by_name(t->name, FALSE);
-
- if (ci != NULL)
- {
- set_cur_connection(ci);
- unroute_connection(ci);
- set_cur_connection(c);
- }
- }
- }
-}
-
-void delete_group(const connection_t *c)
-{
- struct fg_groups *g;
-
- /* find and remove from groups */
- {
- struct fg_groups **pp;
-
- for (pp = &groups; (g = *pp)->connection != c; pp = &(*pp)->next)
- ;
-
- *pp = g->next;
- }
-
- /* find and remove from targets */
- {
- struct fg_targets **pp;
-
- for (pp = &targets; *pp != NULL; )
- {
- struct fg_targets *t = *pp;
-
- if (t->group == g)
- {
- *pp = t->next;
- remove_group_instance(t->group->connection, t->name);
- free(t);
- /* pp is ready for next iteration */
- }
- else
- {
- pp = &t->next;
- }
- }
- }
-
- free(g);
-}