Commit Diff
Diff:
a7d7e7e306128ba3cd5934b7e6e1b4a2718048a3
d9a2aaa34932bcba1f8a4d3509b3272ba92b3d86
Commit:
d9a2aaa34932bcba1f8a4d3509b3272ba92b3d86 (tags/BETA_5)
Tree:
7519e0d2afe79f38a2958e7e07f4318d8f43ef57
Author:
pbug <pbug@delphinusdns.org>
Committer:
pbug <pbug@delphinusdns.org>
Date:
Wed Apr 7 12:52:02 2010 UTC
Message:
* forgot to add this file for BETA_5
blob - /dev/null
blob + 5ac1cc67d9b40918c915b55cbb39a831698cace2 (mode 644)
--- /dev/null
+++ wildcard.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2010 Peter J. Philipp
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "include.h"
+#include "dns.h"
+#include "db.h"
+
+void init_wildcard(void);
+int find_wildcard(struct sockaddr_storage *sst, int family);
+int insert_wildcard(char *address, char *prefixlen);
+extern in_addr_t getmask(int prefixlen);
+extern int getmask6(int prefixlen, struct sockaddr_in6 *sin6);
+
+SLIST_HEAD(listhead, wildentry) wildhead;
+
+struct wildentry {
+ char name[INET6_ADDRSTRLEN];
+ int family;
+ struct sockaddr_storage hostmask;
+ struct sockaddr_storage netmask;
+ u_int8_t prefixlen;
+ SLIST_ENTRY(wildentry) entries;
+} *wn1, *wn2, *wnp;
+
+
+static const char rcsid[] = "$Id: wildcard.c,v 1.1 2010/04/07 12:52:02 pbug Exp $";
+
+/*
+ * INIT_WILDCARD - initialize the wildcard singly linked list
+ */
+
+void
+init_wildcard(void)
+{
+ SLIST_INIT(&wildhead);
+ return;
+}
+
+/*
+ * INSERT_WILDCARD - insert an address and prefixlen into the wildcard slist
+ */
+
+int
+insert_wildcard(char *address, char *prefixlen)
+{
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ int pnum;
+ int ret;
+
+ pnum = atoi(prefixlen);
+ wn2 = malloc(sizeof(struct wildentry)); /* Insert after. */
+
+ if (strchr(address, ':') != NULL) {
+ wn2->family = AF_INET6;
+ sin6 = (struct sockaddr_in6 *)&wn2->hostmask;
+ if ((ret = inet_pton(AF_INET6, address, &sin6->sin6_addr.s6_addr)) != 1)
+ return (-1);
+ sin6->sin6_family = AF_INET6;
+ sin6 = (struct sockaddr_in6 *)&wn2->netmask;
+ sin6->sin6_family = AF_INET6;
+ if (getmask6(pnum, sin6) < 0)
+ return(-1);
+ wn2->prefixlen = pnum;
+ } else {
+
+ wn2->family = AF_INET;
+ sin = (struct sockaddr_in *)&wn2->hostmask;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = inet_addr(address);
+ sin = (struct sockaddr_in *)&wn2->netmask;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = getmask(pnum);
+ wn2->prefixlen = pnum;
+
+ }
+
+ SLIST_INSERT_HEAD(&wildhead, wn2, entries);
+
+ return (0);
+}
+
+/*
+ * FIND_WILDCARD - walk the wildcard list and find the correponding network
+ * if a network matches return 1, if no match is found return
+ * 0.
+ */
+
+int
+find_wildcard(struct sockaddr_storage *sst, int family)
+{
+ struct sockaddr_in *sin, *sin0;
+ struct sockaddr_in6 *sin6, *sin60, *sin61;
+ u_int32_t hostmask, netmask;
+ u_int32_t a;
+#ifdef __amd64
+ u_int64_t *hm[2], *nm[2], *a6[2];
+#else
+ u_int32_t *hm[4], *nm[4], *a6[4];
+#endif
+
+ SLIST_FOREACH(wnp, &wildhead, entries) {
+ if (wnp->family == AF_INET) {
+ if (family != AF_INET)
+ continue;
+ sin = (struct sockaddr_in *)sst;
+ a = sin->sin_addr.s_addr;
+ sin = (struct sockaddr_in *)&wnp->hostmask;
+ sin0 = (struct sockaddr_in *)&wnp->netmask;
+ hostmask = sin->sin_addr.s_addr;
+ netmask = sin0->sin_addr.s_addr;
+ if ((hostmask & netmask) == (a & netmask)) {
+ return (1);
+ } /* if hostmask */
+ } else if (wnp->family == AF_INET6) {
+ if (family != AF_INET6)
+ continue;
+ sin6 = (struct sockaddr_in6 *)sst;
+ sin60 = (struct sockaddr_in6 *)&wnp->hostmask;
+ sin61 = (struct sockaddr_in6 *)&wnp->netmask;
+#ifdef __amd64
+ /*
+ * If this is on a 64 bit machine, we'll benefit
+ * by using 64 bit registers, this should make it
+ * a tad faster...
+ */
+ hm[0] = (u_int64_t *)&sin60->sin6_addr.s6_addr;
+ hm[1] = (hm[0] + 1);
+ nm[0] = (u_int64_t *)&sin61->sin6_addr.s6_addr;
+ nm[1] = (nm[0] + 1);
+ a6[0] = (u_int64_t *)&sin6->sin6_addr.s6_addr;
+ a6[1] = (a6[0] + 1);
+ if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
+ ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))) {
+#else
+ hm[0] = (u_int32_t *)&sin60->sin6_addr.s6_addr;
+ hm[1] = (hm[0] + 1); hm[2] = (hm[1] + 1);
+ hm[3] = (hm[2] + 1);
+ nm[0] = (u_int32_t *)&sin61->sin6_addr.s6_addr;
+ nm[1] = (nm[0] + 1); nm[2] = (nm[1] + 1);
+ nm[3] = (nm[2] + 1);
+ a6[0] = (u_int32_t *)&sin6->sin6_addr.s6_addr;
+ a6[1] = (a6[0] + 1); a6[2] = (a6[1] + 1);
+ a6[3] = (a6[2] + 1);
+
+ if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
+ ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))&&
+ ((*hm[2] & *nm[2]) == (*a6[2] & *nm[2]))&&
+ ((*hm[3] & *nm[3]) == (*a6[3] & *nm[3]))) {
+#endif
+
+ return (1);
+ } /* if ip6 address */
+
+ } /* if AF_INET6 */
+ } /* SLIST */
+
+ return (0);
+}
repomaster@centroid.eu