summaryrefslogtreecommitdiffstats
path: root/usr.sbin/faithd/prefix.c
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
committerume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
commit832f8d224926758a9ae0b23a6b45353e44fbc87a (patch)
treea79fc7ad2b97862c4a404f352f0211ad93a7b5f1 /usr.sbin/faithd/prefix.c
parent2693854b01a52b0395a91322aa3edf926bddff38 (diff)
downloadFreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.zip
FreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.tar.gz
Sync with recent KAME.
This work was based on kame-20010528-freebsd43-snap.tgz and some critical problem after the snap was out were fixed. There are many many changes since last KAME merge. TODO: - The definitions of SADB_* in sys/net/pfkeyv2.h are still different from RFC2407/IANA assignment because of binary compatibility issue. It should be fixed under 5-CURRENT. - ip6po_m member of struct ip6_pktopts is no longer used. But, it is still there because of binary compatibility issue. It should be removed under 5-CURRENT. Reviewed by: itojun Obtained from: KAME MFC after: 3 weeks
Diffstat (limited to 'usr.sbin/faithd/prefix.c')
-rw-r--r--usr.sbin/faithd/prefix.c360
1 files changed, 360 insertions, 0 deletions
diff --git a/usr.sbin/faithd/prefix.c b/usr.sbin/faithd/prefix.c
new file mode 100644
index 0000000..739ae56
--- /dev/null
+++ b/usr.sbin/faithd/prefix.c
@@ -0,0 +1,360 @@
+/* $KAME: prefix.c,v 1.8 2000/11/24 06:16:56 itojun Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (C) 2000 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#ifndef offsetof
+#define offsetof(type, member) ((size_t)(u_long)(&((type *)0)->member))
+#endif
+
+#include "faithd.h"
+#include "prefix.h"
+
+static int prefix_set __P((const char *, struct prefix *, int));
+static struct config *config_load1 __P((const char *));
+#if 0
+static void config_show1 __P((const struct config *));
+static void config_show __P((void));
+#endif
+
+struct config *config_list = NULL;
+#ifdef NI_WITHSCOPEID
+const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
+#else
+const int niflags = NI_NUMERICHOST;
+#endif
+
+static int
+prefix_set(s, prefix, slash)
+ const char *s;
+ struct prefix *prefix;
+ int slash;
+{
+ char *p, *q, *r;
+ struct addrinfo hints, *res = NULL;
+ int max;
+ char *a;
+
+ p = strdup(s);
+ q = strchr(p, '/');
+ if (q) {
+ if (!slash)
+ goto fail;
+ *q++ = '\0';
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ hints.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(p, "0", &hints, &res))
+ goto fail;
+ if (res->ai_next || res->ai_addrlen > sizeof(prefix->a))
+ goto fail;
+ memcpy(&prefix->a, res->ai_addr, res->ai_addrlen);
+
+ switch (prefix->a.ss_family) {
+ case AF_INET:
+ max = 32;
+ a = (char *)&((struct sockaddr_in *)&prefix->a)->sin_addr;
+ break;
+ case AF_INET6:
+ max = 128;
+ a = (char *)&((struct sockaddr_in6 *)&prefix->a)->sin6_addr;
+ break;
+ default:
+ a = NULL;
+ max = -1;
+ break;
+ }
+
+ if (q) {
+ r = NULL;
+ prefix->l = (int)strtoul(q, &r, 10);
+ if (!*q || *r)
+ goto fail;
+ if (prefix->l < 0 || prefix->l > max)
+ goto fail;
+ } else
+ prefix->l = max;
+
+ if (p)
+ free(p);
+ if (res)
+ freeaddrinfo(res);
+ return 0;
+
+fail:
+ if (p)
+ free(p);
+ if (res)
+ freeaddrinfo(res);
+ return -1;
+}
+
+const char *
+prefix_string(prefix)
+ const struct prefix *prefix;
+{
+ static char buf[NI_MAXHOST + 20];
+ char hbuf[NI_MAXHOST];
+
+ if (getnameinfo((struct sockaddr *)&prefix->a, prefix->a.ss_len, hbuf,
+ sizeof(hbuf), NULL, 0, niflags))
+ return NULL;
+ snprintf(buf, sizeof(buf), "%s/%d", hbuf, prefix->l);
+ return buf;
+}
+
+int
+prefix_match(prefix, sa)
+ const struct prefix *prefix;
+ const struct sockaddr *sa;
+{
+ struct sockaddr_storage a, b;
+ char *pa, *pb;
+ int off, l;
+
+ if (prefix->a.ss_family != sa->sa_family ||
+ prefix->a.ss_len != sa->sa_len)
+ return 0;
+
+ if (prefix->a.ss_len > sizeof(a) || sa->sa_len > sizeof(b))
+ return 0;
+
+ switch (prefix->a.ss_family) {
+ case AF_INET:
+ off = offsetof(struct sockaddr_in, sin_addr);
+ break;
+ case AF_INET6:
+ off = offsetof(struct sockaddr_in6, sin6_addr);
+ break;
+ default:
+ if (memcmp(&prefix->a, sa, prefix->a.ss_len) != 0)
+ return 0;
+ else
+ return 1;
+ }
+
+ memcpy(&a, &prefix->a, prefix->a.ss_len);
+ memcpy(&b, sa, sa->sa_len);
+ l = prefix->l / 8 + (prefix->l % 8 ? 1 : 0);
+
+ /* overrun check */
+ if (off + l > a.ss_len)
+ return 0;
+
+ pa = ((char *)&a) + off;
+ pb = ((char *)&b) + off;
+ if (prefix->l % 8) {
+ pa[prefix->l / 8] &= 0xff00 >> (prefix->l % 8);
+ pb[prefix->l / 8] &= 0xff00 >> (prefix->l % 8);
+ }
+ if (memcmp(pa, pb, l) != 0)
+ return 0;
+ else
+ return 1;
+}
+
+/*
+ * prefix/prefixlen permit/deny prefix/prefixlen [srcaddr]
+ * 3ffe::/16 permit 10.0.0.0/8 10.1.1.1
+ */
+static struct config *
+config_load1(line)
+ const char *line;
+{
+ struct config *conf;
+ char buf[BUFSIZ];
+ char *p;
+ char *token[4];
+ int i;
+
+ if (strlen(line) + 1 > sizeof(buf))
+ return NULL;
+ strlcpy(buf, line, sizeof(buf));
+
+ p = strchr(buf, '\n');
+ if (!p)
+ return NULL;
+ *p = '\0';
+ p = strchr(buf, '#');
+ if (p)
+ *p = '\0';
+ if (strlen(buf) == 0)
+ return NULL;
+
+ p = buf;
+ memset(token, 0, sizeof(token));
+ for (i = 0; i < sizeof(token) / sizeof(token[0]); i++) {
+ token[i] = strtok(p, "\t ");
+ p = NULL;
+ if (token[i] == NULL)
+ break;
+ }
+ /* extra tokens? */
+ if (strtok(p, "\t ") != NULL)
+ return NULL;
+ /* insufficient tokens */
+ switch (i) {
+ case 3:
+ case 4:
+ break;
+ default:
+ return NULL;
+ }
+
+ conf = (struct config *)malloc(sizeof(*conf));
+ if (conf == NULL)
+ return NULL;
+ memset(conf, 0, sizeof(*conf));
+
+ if (strcasecmp(token[1], "permit") == 0)
+ conf->permit = 1;
+ else if (strcasecmp(token[1], "deny") == 0)
+ conf->permit = 0;
+ else {
+ /* invalid keyword is considered as "deny" */
+ conf->permit = 0;
+ }
+
+ if (prefix_set(token[0], &conf->match, 1) < 0)
+ goto fail;
+ if (prefix_set(token[2], &conf->dest, 1) < 0)
+ goto fail;
+ if (token[3]) {
+ if (prefix_set(token[3], &conf->src, 0) < 0)
+ goto fail;
+ }
+
+ return conf;
+
+fail:
+ free(conf);
+ return NULL;
+}
+
+int
+config_load(configfile)
+ const char *configfile;
+{
+ FILE *fp;
+ char buf[BUFSIZ];
+ struct config *conf, *p;
+ struct config sentinel;
+
+ config_list = NULL;
+
+ if (!configfile)
+ configfile = _PATH_PREFIX_CONF;
+ fp = fopen(configfile, "r");
+ if (fp == NULL)
+ return -1;
+
+ p = &sentinel;
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ conf = config_load1(buf);
+ if (conf) {
+ p->next = conf;
+ p = p->next;
+ }
+ }
+ config_list = sentinel.next;
+
+ fclose(fp);
+ return 0;
+}
+
+#if 0
+static void
+config_show1(conf)
+ const struct config *conf;
+{
+ const char *p;
+
+ p = prefix_string(&conf->match);
+ printf("%s", p ? p : "?");
+
+ if (conf->permit)
+ printf(" permit");
+ else
+ printf(" deny");
+
+ p = prefix_string(&conf->dest);
+ printf(" %s", p ? p : "?");
+
+ printf("\n");
+}
+
+static void
+config_show()
+{
+ struct config *conf;
+
+ for (conf = config_list; conf; conf = conf->next)
+ config_show1(conf);
+}
+#endif
+
+const struct config *
+config_match(sa1, sa2)
+ struct sockaddr *sa1, *sa2;
+{
+ static struct config conf;
+ const struct config *p;
+
+ if (sa1->sa_len > sizeof(conf.match.a) ||
+ sa2->sa_len > sizeof(conf.dest.a))
+ return NULL;
+
+ memset(&conf, 0, sizeof(conf));
+ if (!config_list) {
+ conf.permit = 1;
+ memcpy(&conf.match.a, sa1, sa1->sa_len);
+ memcpy(&conf.dest.a, sa2, sa2->sa_len);
+ return &conf;
+ }
+
+ for (p = config_list; p; p = p->next)
+ if (prefix_match(&p->match, sa1) && prefix_match(&p->dest, sa2))
+ return p;
+
+ return NULL;
+}
OpenPOWER on IntegriCloud